add license comments
[cparser] / ast.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18  * 02111-1307, USA.
19  */
20 #include <config.h>
21
22 #include "ast_t.h"
23 #include "type_t.h"
24
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29
30 #include "adt/error.h"
31
32 struct obstack ast_obstack;
33
34 static FILE *out;
35 static int   indent;
36
37 /** If set, implicit casts are printed. */
38 bool print_implicit_casts = false;
39
40 /** If set parenthesis are printed to indicate operator precedence. */
41 bool print_parenthesis = false;
42
43 static void print_statement(const statement_t *statement);
44 static void print_expression_prec(const expression_t *expression, unsigned prec);
45
46 void change_indent(int delta)
47 {
48         indent += delta;
49         assert(indent >= 0);
50 }
51
52 void print_indent(void)
53 {
54         for(int i = 0; i < indent; ++i)
55                 fprintf(out, "\t");
56 }
57
58 enum precedence_t {
59         PREC_BOTTOM  =  0,
60         PREC_COMMA   =  2, /* ,                                    left to right */
61         PREC_ASSIGN  =  4, /* = += -= *= /= %= <<= >>= &= ^= |=    right to left */
62         PREC_COND    =  6, /* ?:                                   right to left */
63         PREC_LOG_OR  =  8, /* ||                                   left to right */
64         PREC_LOG_AND = 10, /* &&                                   left to right */
65         PREC_BIT_OR  = 12, /* |                                    left to right */
66         PREC_BIT_XOR = 14, /* ^                                    left to right */
67         PREC_BIT_AND = 16, /* &                                    left to right */
68         PREC_EQ      = 18, /* == !=                                left to right */
69         PREC_CMP     = 20, /* < <= > >=                            left to right */
70         PREC_SHF     = 22, /* << >>                                left to right */
71         PREC_PLUS    = 24, /* + -                                  left to right */
72         PREC_MUL     = 26, /* * / %                                left to right */
73         PREC_UNARY   = 28, /* ! ~ ++ -- + - (type) * & sizeof      right to left */
74         PREC_ACCESS  = 30, /* () [] -> .                           left to right */
75         PREC_PRIM    = 32, /* primary */
76         PREC_TOP     = 34
77 };
78
79 /**
80  * Returns 1 if a given precedence level has right-to-left
81  * associativity, else -1.
82  *
83  * @param precedence   the operator precedence
84  */
85 static int right_to_left(unsigned precedence) {
86         return (precedence == PREC_ASSIGN || precedence == PREC_COND ||
87                 precedence == PREC_UNARY) ? 1 : -1;
88 }
89
90 /**
91  * Return the precedence of an expression given by its kind.
92  *
93  * @param kind   the expression kind
94  */
95 static unsigned get_expression_precedence(expression_kind_t kind)
96 {
97         static const unsigned prec[] = {
98                 [EXPR_UNKNOWN]                   = PREC_PRIM,
99                 [EXPR_INVALID]                   = PREC_PRIM,
100                 [EXPR_REFERENCE]                 = PREC_PRIM,
101                 [EXPR_CHAR_CONST]                = PREC_PRIM,
102                 [EXPR_CONST]                     = PREC_PRIM,
103                 [EXPR_STRING_LITERAL]            = PREC_PRIM,
104                 [EXPR_WIDE_STRING_LITERAL]       = PREC_PRIM,
105                 [EXPR_COMPOUND_LITERAL]          = PREC_UNARY,
106                 [EXPR_CALL]                      = PREC_PRIM,
107                 [EXPR_CONDITIONAL]               = PREC_COND,
108                 [EXPR_SELECT]                    = PREC_ACCESS,
109                 [EXPR_ARRAY_ACCESS]              = PREC_ACCESS,
110                 [EXPR_SIZEOF]                    = PREC_UNARY,
111                 [EXPR_CLASSIFY_TYPE]             = PREC_UNARY,
112                 [EXPR_ALIGNOF]                   = PREC_UNARY,
113
114                 [EXPR_FUNCTION]                  = PREC_PRIM,
115                 [EXPR_PRETTY_FUNCTION]           = PREC_PRIM,
116                 [EXPR_BUILTIN_SYMBOL]            = PREC_PRIM,
117                 [EXPR_BUILTIN_CONSTANT_P]        = PREC_PRIM,
118                 [EXPR_BUILTIN_PREFETCH]          = PREC_PRIM,
119                 [EXPR_OFFSETOF]                  = PREC_PRIM,
120                 [EXPR_VA_START]                  = PREC_PRIM,
121                 [EXPR_VA_ARG]                    = PREC_PRIM,
122                 [EXPR_STATEMENT]                 = PREC_ACCESS,
123
124                 [EXPR_UNARY_NEGATE]              = PREC_UNARY,
125                 [EXPR_UNARY_PLUS]                = PREC_UNARY,
126                 [EXPR_UNARY_BITWISE_NEGATE]      = PREC_UNARY,
127                 [EXPR_UNARY_NOT]                 = PREC_UNARY,
128                 [EXPR_UNARY_DEREFERENCE]         = PREC_UNARY,
129                 [EXPR_UNARY_TAKE_ADDRESS]        = PREC_UNARY,
130                 [EXPR_UNARY_POSTFIX_INCREMENT]   = PREC_UNARY,
131                 [EXPR_UNARY_POSTFIX_DECREMENT]   = PREC_UNARY,
132                 [EXPR_UNARY_PREFIX_INCREMENT]    = PREC_UNARY,
133                 [EXPR_UNARY_PREFIX_DECREMENT]    = PREC_UNARY,
134                 [EXPR_UNARY_CAST]                = PREC_UNARY,
135                 [EXPR_UNARY_CAST_IMPLICIT]       = PREC_UNARY,
136                 [EXPR_UNARY_ASSUME]              = PREC_PRIM,
137                 [EXPR_UNARY_BITFIELD_EXTRACT]    = PREC_ACCESS,
138
139                 [EXPR_BINARY_ADD]                = PREC_PLUS,
140                 [EXPR_BINARY_SUB]                = PREC_PLUS,
141                 [EXPR_BINARY_MUL]                = PREC_MUL,
142                 [EXPR_BINARY_DIV]                = PREC_MUL,
143                 [EXPR_BINARY_MOD]                = PREC_MUL,
144                 [EXPR_BINARY_EQUAL]              = PREC_EQ,
145                 [EXPR_BINARY_NOTEQUAL]           = PREC_EQ,
146                 [EXPR_BINARY_LESS]               = PREC_CMP,
147                 [EXPR_BINARY_LESSEQUAL]          = PREC_CMP,
148                 [EXPR_BINARY_GREATER]            = PREC_CMP,
149                 [EXPR_BINARY_GREATEREQUAL]       = PREC_CMP,
150                 [EXPR_BINARY_BITWISE_AND]        = PREC_BIT_AND,
151                 [EXPR_BINARY_BITWISE_OR]         = PREC_BIT_OR,
152                 [EXPR_BINARY_BITWISE_XOR]        = PREC_BIT_XOR,
153                 [EXPR_BINARY_LOGICAL_AND]        = PREC_LOG_AND,
154                 [EXPR_BINARY_LOGICAL_OR]         = PREC_LOG_OR,
155                 [EXPR_BINARY_SHIFTLEFT]          = PREC_SHF,
156                 [EXPR_BINARY_SHIFTRIGHT]         = PREC_SHF,
157                 [EXPR_BINARY_ASSIGN]             = PREC_ASSIGN,
158                 [EXPR_BINARY_MUL_ASSIGN]         = PREC_ASSIGN,
159                 [EXPR_BINARY_DIV_ASSIGN]         = PREC_ASSIGN,
160                 [EXPR_BINARY_MOD_ASSIGN]         = PREC_ASSIGN,
161                 [EXPR_BINARY_ADD_ASSIGN]         = PREC_ASSIGN,
162                 [EXPR_BINARY_SUB_ASSIGN]         = PREC_ASSIGN,
163                 [EXPR_BINARY_SHIFTLEFT_ASSIGN]   = PREC_ASSIGN,
164                 [EXPR_BINARY_SHIFTRIGHT_ASSIGN]  = PREC_ASSIGN,
165                 [EXPR_BINARY_BITWISE_AND_ASSIGN] = PREC_ASSIGN,
166                 [EXPR_BINARY_BITWISE_XOR_ASSIGN] = PREC_ASSIGN,
167                 [EXPR_BINARY_BITWISE_OR_ASSIGN]  = PREC_ASSIGN,
168                 [EXPR_BINARY_COMMA]              = PREC_COMMA,
169
170                 [EXPR_BINARY_BUILTIN_EXPECT]     = PREC_PRIM,
171                 [EXPR_BINARY_ISGREATER]          = PREC_PRIM,
172                 [EXPR_BINARY_ISGREATEREQUAL]     = PREC_PRIM,
173                 [EXPR_BINARY_ISLESS]             = PREC_PRIM,
174                 [EXPR_BINARY_ISLESSEQUAL]        = PREC_PRIM,
175                 [EXPR_BINARY_ISLESSGREATER]      = PREC_PRIM,
176                 [EXPR_BINARY_ISUNORDERED]        = PREC_PRIM
177         };
178         assert((unsigned)kind < (sizeof(prec)/sizeof(prec[0])));
179         unsigned res = prec[kind];
180
181         assert(res != PREC_BOTTOM);
182         return res;
183 }
184
185 /**
186  * Print a constant expression.
187  *
188  * @param cnst  the constant expression
189  */
190 static void print_const(const const_expression_t *cnst)
191 {
192         if(cnst->base.type == NULL)
193                 return;
194
195         const type_t *const type = skip_typeref(cnst->base.type);
196
197         if (is_type_integer(type)) {
198                 fprintf(out, "%lld", cnst->v.int_value);
199         } else if (is_type_float(type)) {
200                 fprintf(out, "%Lf", cnst->v.float_value);
201         } else {
202                 panic("unknown constant");
203         }
204 }
205
206 /**
207  * Print a quoted string constant.
208  *
209  * @param string  the string constant
210  * @param border  the border char
211  */
212 static void print_quoted_string(const string_t *const string, char border)
213 {
214         fputc(border, out);
215         const char *end = string->begin + string->size - 1;
216         for (const char *c = string->begin; c != end; ++c) {
217                 if (*c == border) {
218                         fputc('\\', out);
219                 }
220                 switch(*c) {
221                 case '\\':  fputs("\\\\", out); break;
222                 case '\a':  fputs("\\a", out); break;
223                 case '\b':  fputs("\\b", out); break;
224                 case '\f':  fputs("\\f", out); break;
225                 case '\n':  fputs("\\n", out); break;
226                 case '\r':  fputs("\\r", out); break;
227                 case '\t':  fputs("\\t", out); break;
228                 case '\v':  fputs("\\v", out); break;
229                 case '\?':  fputs("\\?", out); break;
230                 default:
231                         if(!isprint(*c)) {
232                                 fprintf(out, "\\%03o", *c);
233                                 break;
234                         }
235                         fputc(*c, out);
236                         break;
237                 }
238         }
239         fputc(border, out);
240 }
241
242 /**
243  * Print a constant character expression.
244  *
245  * @param cnst  the constant character expression
246  */
247 static void print_char_const(const const_expression_t *cnst)
248 {
249         print_quoted_string(&cnst->v.chars, '\'');
250 }
251
252 /**
253  * Prints a string literal expression.
254  *
255  * @param string_literal  the string literal expression
256  */
257 static void print_string_literal(
258                 const string_literal_expression_t *string_literal)
259 {
260         print_quoted_string(&string_literal->value, '"');
261 }
262
263 /**
264  * Prints a wide string literal expression.
265  *
266  * @param wstr  the wide string literal expression
267  */
268 static void print_quoted_wide_string(const wide_string_t *const wstr)
269 {
270         fputs("L\"", out);
271         for (const wchar_rep_t *c = wstr->begin, *end = wstr->begin + wstr->size - 1;
272              c != end; ++c) {
273                 switch (*c) {
274                         case L'\"':  fputs("\\\"", out); break;
275                         case L'\\':  fputs("\\\\", out); break;
276                         case L'\a':  fputs("\\a",  out); break;
277                         case L'\b':  fputs("\\b",  out); break;
278                         case L'\f':  fputs("\\f",  out); break;
279                         case L'\n':  fputs("\\n",  out); break;
280                         case L'\r':  fputs("\\r",  out); break;
281                         case L'\t':  fputs("\\t",  out); break;
282                         case L'\v':  fputs("\\v",  out); break;
283                         case L'\?':  fputs("\\?",  out); break;
284                         default: {
285                                 const unsigned tc = *c;
286                                 if (tc < 0x80U) {
287                                         if (!isprint(*c))  {
288                                                 fprintf(out, "\\%03o", (char)*c);
289                                         } else {
290                                                 fputc(*c, out);
291                                         }
292                                 } else if (tc < 0x800) {
293                                         fputc(0xC0 | (tc >> 6),   out);
294                                         fputc(0x80 | (tc & 0x3F), out);
295                                 } else if (tc < 0x10000) {
296                                         fputc(0xE0 | ( tc >> 12),         out);
297                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
298                                         fputc(0x80 | ( tc        & 0x3F), out);
299                                 } else {
300                                         fputc(0xF0 | ( tc >> 18),         out);
301                                         fputc(0x80 | ((tc >> 12) & 0x3F), out);
302                                         fputc(0x80 | ((tc >>  6) & 0x3F), out);
303                                         fputc(0x80 | ( tc        & 0x3F), out);
304                                 }
305                         }
306                 }
307         }
308         fputc('"', out);
309 }
310
311 static void print_wide_string_literal(
312         const wide_string_literal_expression_t *const wstr)
313 {
314         print_quoted_wide_string(&wstr->value);
315 }
316
317 static void print_compound_literal(
318                 const compound_literal_expression_t *expression)
319 {
320         fputc('(', out);
321         print_type(expression->type);
322         fputs(") ", out);
323         print_initializer(expression->initializer);
324 }
325
326 /**
327  * Prints a call expression.
328  *
329  * @param call  the call expression
330  */
331 static void print_call_expression(const call_expression_t *call)
332 {
333         unsigned prec = get_expression_precedence(call->base.kind);
334         print_expression_prec(call->function, prec);
335         fprintf(out, "(");
336         call_argument_t *argument = call->arguments;
337         int              first    = 1;
338         while(argument != NULL) {
339                 if(!first) {
340                         fprintf(out, ", ");
341                 } else {
342                         first = 0;
343                 }
344                 print_expression_prec(argument->expression, PREC_COMMA + 1);
345
346                 argument = argument->next;
347         }
348         fprintf(out, ")");
349 }
350
351 /**
352  * Prints a binary expression.
353  *
354  * @param binexpr   the binary expression
355  */
356 static void print_binary_expression(const binary_expression_t *binexpr)
357 {
358         unsigned prec = get_expression_precedence(binexpr->base.kind);
359         int      r2l  = right_to_left(prec);
360
361         if(binexpr->base.kind == EXPR_BINARY_BUILTIN_EXPECT) {
362                 fputs("__builtin_expect(", out);
363                 print_expression_prec(binexpr->left, prec);
364                 fputs(", ", out);
365                 print_expression_prec(binexpr->right, prec);
366                 fputc(')', out);
367                 return;
368         }
369
370         print_expression_prec(binexpr->left, prec + r2l);
371         if (binexpr->base.kind != EXPR_BINARY_COMMA) {
372                 fputc(' ', out);
373         }
374         switch (binexpr->base.kind) {
375         case EXPR_BINARY_COMMA:              fputs(",", out);     break;
376         case EXPR_BINARY_ASSIGN:             fputs("=", out);     break;
377         case EXPR_BINARY_ADD:                fputs("+", out);     break;
378         case EXPR_BINARY_SUB:                fputs("-", out);     break;
379         case EXPR_BINARY_MUL:                fputs("*", out);     break;
380         case EXPR_BINARY_MOD:                fputs("%", out);     break;
381         case EXPR_BINARY_DIV:                fputs("/", out);     break;
382         case EXPR_BINARY_BITWISE_OR:         fputs("|", out);     break;
383         case EXPR_BINARY_BITWISE_AND:        fputs("&", out);     break;
384         case EXPR_BINARY_BITWISE_XOR:        fputs("^", out);     break;
385         case EXPR_BINARY_LOGICAL_OR:         fputs("||", out);    break;
386         case EXPR_BINARY_LOGICAL_AND:        fputs("&&", out);    break;
387         case EXPR_BINARY_NOTEQUAL:           fputs("!=", out);    break;
388         case EXPR_BINARY_EQUAL:              fputs("==", out);    break;
389         case EXPR_BINARY_LESS:               fputs("<", out);     break;
390         case EXPR_BINARY_LESSEQUAL:          fputs("<=", out);    break;
391         case EXPR_BINARY_GREATER:            fputs(">", out);     break;
392         case EXPR_BINARY_GREATEREQUAL:       fputs(">=", out);    break;
393         case EXPR_BINARY_SHIFTLEFT:          fputs("<<", out);    break;
394         case EXPR_BINARY_SHIFTRIGHT:         fputs(">>", out);    break;
395
396         case EXPR_BINARY_ADD_ASSIGN:         fputs("+=", out);    break;
397         case EXPR_BINARY_SUB_ASSIGN:         fputs("-=", out);    break;
398         case EXPR_BINARY_MUL_ASSIGN:         fputs("*=", out);    break;
399         case EXPR_BINARY_MOD_ASSIGN:         fputs("%=", out);    break;
400         case EXPR_BINARY_DIV_ASSIGN:         fputs("/=", out);    break;
401         case EXPR_BINARY_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
402         case EXPR_BINARY_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
403         case EXPR_BINARY_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
404         case EXPR_BINARY_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
405         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
406         default: panic("invalid binexpression found");
407         }
408         fputc(' ', out);
409         print_expression_prec(binexpr->right, prec - r2l);
410 }
411
412 /**
413  * Prints an unary expression.
414  *
415  * @param unexpr   the unary expression
416  */
417 static void print_unary_expression(const unary_expression_t *unexpr)
418 {
419         unsigned prec = get_expression_precedence(unexpr->base.kind);
420         switch(unexpr->base.kind) {
421         case EXPR_UNARY_NEGATE:           fputs("-", out);  break;
422         case EXPR_UNARY_PLUS:             fputs("+", out);  break;
423         case EXPR_UNARY_NOT:              fputs("!", out);  break;
424         case EXPR_UNARY_BITWISE_NEGATE:   fputs("~", out);  break;
425         case EXPR_UNARY_PREFIX_INCREMENT: fputs("++", out); break;
426         case EXPR_UNARY_PREFIX_DECREMENT: fputs("--", out); break;
427         case EXPR_UNARY_DEREFERENCE:      fputs("*", out);  break;
428         case EXPR_UNARY_TAKE_ADDRESS:     fputs("&", out);  break;
429
430         case EXPR_UNARY_BITFIELD_EXTRACT:
431                 print_expression_prec(unexpr->value, prec);
432                 return;
433
434         case EXPR_UNARY_POSTFIX_INCREMENT:
435                 print_expression_prec(unexpr->value, prec);
436                 fputs("++", out);
437                 return;
438         case EXPR_UNARY_POSTFIX_DECREMENT:
439                 print_expression_prec(unexpr->value, prec);
440                 fputs("--", out);
441                 return;
442         case EXPR_UNARY_CAST_IMPLICIT:
443                 if(!print_implicit_casts) {
444                         print_expression_prec(unexpr->value, prec);
445                         return;
446                 }
447                 /* fallthrough */
448         case EXPR_UNARY_CAST:
449                 fputc('(', out);
450                 print_type(unexpr->base.type);
451                 fputc(')', out);
452                 break;
453         case EXPR_UNARY_ASSUME:
454                 fputs("__assume(", out);
455                 print_expression_prec(unexpr->value, PREC_COMMA + 1);
456                 fputc(')', out);
457                 return;
458         default:
459                 panic("invalid unary expression found");
460         }
461         print_expression_prec(unexpr->value, prec);
462 }
463
464 /**
465  * Prints a reference expression.
466  *
467  * @param ref   the reference expression
468  */
469 static void print_reference_expression(const reference_expression_t *ref)
470 {
471         fprintf(out, "%s", ref->declaration->symbol->string);
472 }
473
474 /**
475  * Prints an array expression.
476  *
477  * @param expression   the array expression
478  */
479 static void print_array_expression(const array_access_expression_t *expression)
480 {
481         unsigned prec = get_expression_precedence(expression->base.kind);
482         if(!expression->flipped) {
483                 print_expression_prec(expression->array_ref, prec);
484                 fputc('[', out);
485                 print_expression_prec(expression->index, prec);
486                 fputc(']', out);
487         } else {
488                 print_expression_prec(expression->index, prec);
489                 fputc('[', out);
490                 print_expression_prec(expression->array_ref, prec);
491                 fputc(']', out);
492         }
493 }
494
495 /**
496  * Prints a typeproperty expression (sizeof or __alignof__).
497  *
498  * @param expression   the type property expression
499  */
500 static void print_typeprop_expression(const typeprop_expression_t *expression)
501 {
502         if (expression->base.kind == EXPR_SIZEOF) {
503                 fputs("sizeof", out);
504         } else {
505                 assert(expression->base.kind == EXPR_ALIGNOF);
506                 fputs("__alignof__", out);
507         }
508         if(expression->tp_expression != NULL) {
509                 /* always print the '()' here, sizeof x is right but unusual */
510                 fputc('(', out);
511                 print_expression_prec(expression->tp_expression, PREC_ACCESS);
512                 fputc(')', out);
513         } else {
514                 fputc('(', out);
515                 print_type(expression->type);
516                 fputc(')', out);
517         }
518 }
519
520 /**
521  * Prints an builtin symbol.
522  *
523  * @param expression   the builtin symbol expression
524  */
525 static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
526 {
527         fputs(expression->symbol->string, out);
528 }
529
530 /**
531  * Prints a builtin constant expression.
532  *
533  * @param expression   the builtin constant expression
534  */
535 static void print_builtin_constant(const builtin_constant_expression_t *expression)
536 {
537         fputs("__builtin_constant_p(", out);
538         print_expression_prec(expression->value, PREC_COMMA + 1);
539         fputc(')', out);
540 }
541
542 /**
543  * Prints a builtin prefetch expression.
544  *
545  * @param expression   the builtin prefetch expression
546  */
547 static void print_builtin_prefetch(const builtin_prefetch_expression_t *expression)
548 {
549         fputs("__builtin_prefetch(", out);
550         print_expression_prec(expression->adr, PREC_COMMA + 1);
551         if (expression->rw) {
552                 fputc(',', out);
553                 print_expression_prec(expression->rw, PREC_COMMA + 1);
554         }
555         if (expression->locality) {
556                 fputc(',', out);
557                 print_expression_prec(expression->locality, PREC_COMMA + 1);
558         }
559         fputc(')', out);
560 }
561
562 /**
563  * Prints a conditional expression.
564  *
565  * @param expression   the conditional expression
566  */
567 static void print_conditional(const conditional_expression_t *expression)
568 {
569         unsigned prec = get_expression_precedence(expression->base.kind);
570         fputs("(", out);
571         print_expression_prec(expression->condition, prec);
572         fputs(" ? ", out);
573         print_expression_prec(expression->true_expression, prec);
574         fputs(" : ", out);
575         print_expression_prec(expression->false_expression, prec);
576         fputs(")", out);
577 }
578
579 /**
580  * Prints a va_start expression.
581  *
582  * @param expression   the va_start expression
583  */
584 static void print_va_start(const va_start_expression_t *const expression)
585 {
586         fputs("__builtin_va_start(", out);
587         print_expression_prec(expression->ap, PREC_COMMA + 1);
588         fputs(", ", out);
589         fputs(expression->parameter->symbol->string, out);
590         fputs(")", out);
591 }
592
593 /**
594  * Prints a va_arg expression.
595  *
596  * @param expression   the va_arg expression
597  */
598 static void print_va_arg(const va_arg_expression_t *expression)
599 {
600         fputs("__builtin_va_arg(", out);
601         print_expression_prec(expression->ap, PREC_COMMA + 1);
602         fputs(", ", out);
603         print_type(expression->base.type);
604         fputs(")", out);
605 }
606
607 /**
608  * Prints a select expression (. or ->).
609  *
610  * @param expression   the select expression
611  */
612 static void print_select(const select_expression_t *expression)
613 {
614         unsigned prec = get_expression_precedence(expression->base.kind);
615         print_expression_prec(expression->compound, prec);
616         if(is_type_pointer(expression->compound->base.type)) {
617                 fputs("->", out);
618         } else {
619                 fputc('.', out);
620         }
621         fputs(expression->symbol->string, out);
622 }
623
624 /**
625  * Prints a type classify expression.
626  *
627  * @param expr   the type classify expression
628  */
629 static void print_classify_type_expression(
630         const classify_type_expression_t *const expr)
631 {
632         fputs("__builtin_classify_type(", out);
633         print_expression_prec(expr->type_expression, PREC_COMMA + 1);
634         fputc(')', out);
635 }
636
637 /**
638  * Prints a designator.
639  *
640  * @param designator  the designator
641  */
642 static void print_designator(const designator_t *designator)
643 {
644         for ( ; designator != NULL; designator = designator->next) {
645                 if (designator->symbol == NULL) {
646                         fputc('[', out);
647                         print_expression_prec(designator->array_index, PREC_ACCESS);
648                         fputc(']', out);
649                 } else {
650                         fputc('.', out);
651                         fputs(designator->symbol->string, out);
652                 }
653         }
654 }
655
656 /**
657  * Prints an offsetof expression.
658  *
659  * @param expression   the offset expression
660  */
661 static void print_offsetof_expression(const offsetof_expression_t *expression)
662 {
663         fputs("__builtin_offsetof", out);
664         fputc('(', out);
665         print_type(expression->type);
666         fputc(',', out);
667         print_designator(expression->designator);
668         fputc(')', out);
669 }
670
671 /**
672  * Prints a statement expression.
673  *
674  * @param expression   the statement expression
675  */
676 static void print_statement_expression(const statement_expression_t *expression)
677 {
678         fputc('(', out);
679         print_statement(expression->statement);
680         fputc(')', out);
681 }
682
683 /**
684  * Prints an expression with parenthesis if needed.
685  *
686  * @param expression  the expression to print
687  * @param top_prec    the precedence of the user of this expression.
688  */
689 static void print_expression_prec(const expression_t *expression, unsigned top_prec)
690 {
691         unsigned prec = get_expression_precedence(expression->base.kind);
692         if (print_parenthesis && top_prec != PREC_BOTTOM)
693                 top_prec = PREC_TOP;
694         if (top_prec > prec)
695                 fputc('(', out);
696         switch(expression->kind) {
697         case EXPR_UNKNOWN:
698         case EXPR_INVALID:
699                 fprintf(out, "*invalid expression*");
700                 break;
701         case EXPR_CHAR_CONST:
702                 print_char_const(&expression->conste);
703                 break;
704         case EXPR_CONST:
705                 print_const(&expression->conste);
706                 break;
707         case EXPR_FUNCTION:
708         case EXPR_PRETTY_FUNCTION:
709         case EXPR_STRING_LITERAL:
710                 print_string_literal(&expression->string);
711                 break;
712         case EXPR_WIDE_STRING_LITERAL:
713                 print_wide_string_literal(&expression->wide_string);
714                 break;
715         case EXPR_COMPOUND_LITERAL:
716                 print_compound_literal(&expression->compound_literal);
717                 break;
718         case EXPR_CALL:
719                 print_call_expression(&expression->call);
720                 break;
721         EXPR_BINARY_CASES
722                 print_binary_expression(&expression->binary);
723                 break;
724         case EXPR_REFERENCE:
725                 print_reference_expression(&expression->reference);
726                 break;
727         case EXPR_ARRAY_ACCESS:
728                 print_array_expression(&expression->array_access);
729                 break;
730         EXPR_UNARY_CASES
731                 print_unary_expression(&expression->unary);
732                 break;
733         case EXPR_SIZEOF:
734         case EXPR_ALIGNOF:
735                 print_typeprop_expression(&expression->typeprop);
736                 break;
737         case EXPR_BUILTIN_SYMBOL:
738                 print_builtin_symbol(&expression->builtin_symbol);
739                 break;
740         case EXPR_BUILTIN_CONSTANT_P:
741                 print_builtin_constant(&expression->builtin_constant);
742                 break;
743         case EXPR_BUILTIN_PREFETCH:
744                 print_builtin_prefetch(&expression->builtin_prefetch);
745                 break;
746         case EXPR_CONDITIONAL:
747                 print_conditional(&expression->conditional);
748                 break;
749         case EXPR_VA_START:
750                 print_va_start(&expression->va_starte);
751                 break;
752         case EXPR_VA_ARG:
753                 print_va_arg(&expression->va_arge);
754                 break;
755         case EXPR_SELECT:
756                 print_select(&expression->select);
757                 break;
758         case EXPR_CLASSIFY_TYPE:
759                 print_classify_type_expression(&expression->classify_type);
760                 break;
761         case EXPR_OFFSETOF:
762                 print_offsetof_expression(&expression->offsetofe);
763                 break;
764         case EXPR_STATEMENT:
765                 print_statement_expression(&expression->statement);
766                 break;
767
768         default:
769                 /* TODO */
770                 fprintf(out, "some expression of type %d", (int) expression->kind);
771                 break;
772         }
773         if (top_prec > prec)
774                 fputc(')', out);
775 }
776
777 /**
778  * Print an compound statement.
779  *
780  * @param block  the compound statement
781  */
782 static void print_compound_statement(const compound_statement_t *block)
783 {
784         fputs("{\n", out);
785         ++indent;
786
787         statement_t *statement = block->statements;
788         while(statement != NULL) {
789                 if (statement->base.kind == STATEMENT_CASE_LABEL)
790                         --indent;
791                 print_indent();
792                 print_statement(statement);
793
794                 statement = statement->base.next;
795         }
796         --indent;
797         print_indent();
798         fputs("}\n", out);
799 }
800
801 /**
802  * Print a return statement.
803  *
804  * @param statement  the return statement
805  */
806 static void print_return_statement(const return_statement_t *statement)
807 {
808         fprintf(out, "return ");
809         if(statement->value != NULL)
810                 print_expression(statement->value);
811         fputs(";\n", out);
812 }
813
814 /**
815  * Print an expression statement.
816  *
817  * @param statement  the expression statement
818  */
819 static void print_expression_statement(const expression_statement_t *statement)
820 {
821         print_expression(statement->expression);
822         fputs(";\n", out);
823 }
824
825 /**
826  * Print a goto statement.
827  *
828  * @param statement  the goto statement
829  */
830 static void print_goto_statement(const goto_statement_t *statement)
831 {
832         fprintf(out, "goto ");
833         fputs(statement->label->symbol->string, out);
834         fprintf(stderr, "(%p)", (void*) statement->label);
835         fputs(";\n", out);
836 }
837
838 /**
839  * Print a label statement.
840  *
841  * @param statement  the label statement
842  */
843 static void print_label_statement(const label_statement_t *statement)
844 {
845         fprintf(stderr, "(%p)", (void*) statement->label);
846         fprintf(out, "%s:\n", statement->label->symbol->string);
847         if(statement->statement != NULL) {
848                 print_statement(statement->statement);
849         }
850 }
851
852 /**
853  * Print an if statement.
854  *
855  * @param statement  the if statement
856  */
857 static void print_if_statement(const if_statement_t *statement)
858 {
859         fputs("if(", out);
860         print_expression(statement->condition);
861         fputs(") ", out);
862         if(statement->true_statement != NULL) {
863                 print_statement(statement->true_statement);
864         }
865
866         if(statement->false_statement != NULL) {
867                 print_indent();
868                 fputs("else ", out);
869                 print_statement(statement->false_statement);
870         }
871 }
872
873 /**
874  * Print a switch statement.
875  *
876  * @param statement  the switch statement
877  */
878 static void print_switch_statement(const switch_statement_t *statement)
879 {
880         fputs("switch(", out);
881         print_expression(statement->expression);
882         fputs(") ", out);
883         print_statement(statement->body);
884 }
885
886 /**
887  * Print a case label (including the default label).
888  *
889  * @param statement  the case label statement
890  */
891 static void print_case_label(const case_label_statement_t *statement)
892 {
893         if(statement->expression == NULL) {
894                 fputs("default:\n", out);
895         } else {
896                 fputs("case ", out);
897                 print_expression(statement->expression);
898                 if (statement->end_range != NULL) {
899                         fputs(" ... ", out);
900                         print_expression(statement->end_range);
901                 }
902                 fputs(":\n", out);
903         }
904         ++indent;
905         if(statement->statement != NULL) {
906                 if (statement->statement->base.kind == STATEMENT_CASE_LABEL) {
907                         --indent;
908                 }
909                 print_indent();
910                 print_statement(statement->statement);
911         }
912 }
913
914 /**
915  * Print a declaration statement.
916  *
917  * @param statement   the statement
918  */
919 static void print_declaration_statement(
920                 const declaration_statement_t *statement)
921 {
922         int first = 1;
923         declaration_t *declaration = statement->declarations_begin;
924         for( ; declaration != statement->declarations_end->next;
925                declaration = declaration->next) {
926                 if(!first) {
927                         print_indent();
928                 } else {
929                         first = 0;
930                 }
931                 print_declaration(declaration);
932                 fputc('\n', out);
933         }
934 }
935
936 /**
937  * Print a while statement.
938  *
939  * @param statement   the statement
940  */
941 static void print_while_statement(const while_statement_t *statement)
942 {
943         fputs("while(", out);
944         print_expression(statement->condition);
945         fputs(") ", out);
946         print_statement(statement->body);
947 }
948
949 /**
950  * Print a do-while statement.
951  *
952  * @param statement   the statement
953  */
954 static void print_do_while_statement(const do_while_statement_t *statement)
955 {
956         fputs("do ", out);
957         print_statement(statement->body);
958         print_indent();
959         fputs("while(", out);
960         print_expression(statement->condition);
961         fputs(");\n", out);
962 }
963
964 /**
965  * Print a for statement.
966  *
967  * @param statement   the statement
968  */
969 static void print_for_statement(const for_statement_t *statement)
970 {
971         fputs("for(", out);
972         if(statement->scope.declarations != NULL) {
973                 assert(statement->initialisation == NULL);
974                 print_declaration(statement->scope.declarations);
975                 if(statement->scope.declarations->next != NULL) {
976                         panic("multiple declarations in for statement not supported yet");
977                 }
978                 fputc(' ', out);
979         } else {
980                 if(statement->initialisation) {
981                         print_expression(statement->initialisation);
982                 }
983                 fputs("; ", out);
984         }
985         if(statement->condition != NULL) {
986                 print_expression(statement->condition);
987         }
988         fputs("; ", out);
989         if(statement->step != NULL) {
990                 print_expression(statement->step);
991         }
992         fputs(")", out);
993         print_statement(statement->body);
994 }
995
996 /**
997  * Print assembler constraints.
998  *
999  * @param constraints   the constraints
1000  */
1001 static void print_asm_constraints(asm_constraint_t *constraints)
1002 {
1003         asm_constraint_t *constraint = constraints;
1004         for( ; constraint != NULL; constraint = constraint->next) {
1005                 if(constraint != constraints)
1006                         fputs(", ", out);
1007
1008                 if(constraint->symbol) {
1009                         fprintf(out, "[%s] ", constraint->symbol->string);
1010                 }
1011                 print_quoted_string(&constraint->constraints, '"');
1012                 fputs(" (", out);
1013                 print_expression(constraint->expression);
1014                 fputs(")", out);
1015         }
1016 }
1017
1018 /**
1019  * Print assembler clobbers.
1020  *
1021  * @param clobbers   the clobbers
1022  */
1023 static void print_asm_clobbers(asm_clobber_t *clobbers)
1024 {
1025         asm_clobber_t *clobber = clobbers;
1026         for( ; clobber != NULL; clobber = clobber->next) {
1027                 if(clobber != clobbers)
1028                         fputs(", ", out);
1029
1030                 print_quoted_string(&clobber->clobber, '"');
1031         }
1032 }
1033
1034 /**
1035  * Print an assembler statement.
1036  *
1037  * @param statement   the statement
1038  */
1039 static void print_asm_statement(const asm_statement_t *statement)
1040 {
1041         fputs("asm ", out);
1042         if(statement->is_volatile) {
1043                 fputs("volatile ", out);
1044         }
1045         fputs("(", out);
1046         print_quoted_string(&statement->asm_text, '"');
1047         if(statement->inputs == NULL && statement->outputs == NULL
1048                         && statement->clobbers == NULL)
1049                 goto end_of_print_asm_statement;
1050
1051         fputs(" : ", out);
1052         print_asm_constraints(statement->inputs);
1053         if(statement->outputs == NULL && statement->clobbers == NULL)
1054                 goto end_of_print_asm_statement;
1055
1056         fputs(" : ", out);
1057         print_asm_constraints(statement->outputs);
1058         if(statement->clobbers == NULL)
1059                 goto end_of_print_asm_statement;
1060
1061         fputs(" : ", out);
1062         print_asm_clobbers(statement->clobbers);
1063
1064 end_of_print_asm_statement:
1065         fputs(");\n", out);
1066 }
1067
1068 /**
1069  * Print a statement.
1070  *
1071  * @param statement   the statement
1072  */
1073 void print_statement(const statement_t *statement)
1074 {
1075         switch(statement->kind) {
1076         case STATEMENT_COMPOUND:
1077                 print_compound_statement(&statement->compound);
1078                 break;
1079         case STATEMENT_RETURN:
1080                 print_return_statement(&statement->returns);
1081                 break;
1082         case STATEMENT_EXPRESSION:
1083                 print_expression_statement(&statement->expression);
1084                 break;
1085         case STATEMENT_LABEL:
1086                 print_label_statement(&statement->label);
1087                 break;
1088         case STATEMENT_GOTO:
1089                 print_goto_statement(&statement->gotos);
1090                 break;
1091         case STATEMENT_CONTINUE:
1092                 fputs("continue;\n", out);
1093                 break;
1094         case STATEMENT_BREAK:
1095                 fputs("break;\n", out);
1096                 break;
1097         case STATEMENT_IF:
1098                 print_if_statement(&statement->ifs);
1099                 break;
1100         case STATEMENT_SWITCH:
1101                 print_switch_statement(&statement->switchs);
1102                 break;
1103         case STATEMENT_CASE_LABEL:
1104                 print_case_label(&statement->case_label);
1105                 break;
1106         case STATEMENT_DECLARATION:
1107                 print_declaration_statement(&statement->declaration);
1108                 break;
1109         case STATEMENT_WHILE:
1110                 print_while_statement(&statement->whiles);
1111                 break;
1112         case STATEMENT_DO_WHILE:
1113                 print_do_while_statement(&statement->do_while);
1114                 break;
1115         case STATEMENT_FOR:
1116                 print_for_statement(&statement->fors);
1117                 break;
1118         case STATEMENT_ASM:
1119                 print_asm_statement(&statement->asms);
1120                 break;
1121         case STATEMENT_INVALID:
1122                 fprintf(out, "*invalid statement*");
1123                 break;
1124         }
1125 }
1126
1127 /**
1128  * Print a storage class.
1129  *
1130  * @param storage_class   the storage class
1131  */
1132 static void print_storage_class(storage_class_tag_t storage_class)
1133 {
1134         switch(storage_class) {
1135         case STORAGE_CLASS_ENUM_ENTRY:
1136         case STORAGE_CLASS_NONE:
1137                 break;
1138         case STORAGE_CLASS_TYPEDEF:       fputs("typedef ",        out); break;
1139         case STORAGE_CLASS_EXTERN:        fputs("extern ",         out); break;
1140         case STORAGE_CLASS_STATIC:        fputs("static ",         out); break;
1141         case STORAGE_CLASS_AUTO:          fputs("auto ",           out); break;
1142         case STORAGE_CLASS_REGISTER:      fputs("register ",       out); break;
1143         case STORAGE_CLASS_THREAD:        fputs("__thread",        out); break;
1144         case STORAGE_CLASS_THREAD_EXTERN: fputs("extern __thread", out); break;
1145         case STORAGE_CLASS_THREAD_STATIC: fputs("static __thread", out); break;
1146         }
1147 }
1148
1149 /**
1150  * Print an initializer.
1151  *
1152  * @param initializer  the initializer
1153  */
1154 void print_initializer(const initializer_t *initializer)
1155 {
1156         if(initializer == NULL) {
1157                 fputs("{ NIL-INITIALIZER }", out);
1158                 return;
1159         }
1160
1161         switch(initializer->kind) {
1162         case INITIALIZER_VALUE: {
1163                 const initializer_value_t *value = &initializer->value;
1164                 print_expression(value->value);
1165                 return;
1166         }
1167         case INITIALIZER_LIST: {
1168                 assert(initializer->kind == INITIALIZER_LIST);
1169                 fputs("{ ", out);
1170                 const initializer_list_t *list = &initializer->list;
1171
1172                 for(size_t i = 0 ; i < list->len; ++i) {
1173                         const initializer_t *sub_init = list->initializers[i];
1174                         print_initializer(list->initializers[i]);
1175                         if(i < list->len-1 && sub_init->kind != INITIALIZER_DESIGNATOR) {
1176                                 fputs(", ", out);
1177                         }
1178                 }
1179                 fputs(" }", out);
1180                 return;
1181         }
1182         case INITIALIZER_STRING:
1183                 print_quoted_string(&initializer->string.string, '"');
1184                 return;
1185         case INITIALIZER_WIDE_STRING:
1186                 print_quoted_wide_string(&initializer->wide_string.string);
1187                 return;
1188         case INITIALIZER_DESIGNATOR:
1189                 print_designator(initializer->designator.designator);
1190                 fputs(" = ", out);
1191                 return;
1192         }
1193
1194         panic("invalid initializer kind found");
1195 }
1196
1197 /**
1198  * Print a declaration in the NORMAL namespace.
1199  *
1200  * @param declaration  the declaration
1201  */
1202 static void print_normal_declaration(const declaration_t *declaration)
1203 {
1204         print_storage_class((storage_class_tag_t) declaration->declared_storage_class);
1205         if(declaration->is_inline) {
1206                 if (declaration->modifiers & DM_FORCEINLINE)
1207                         fputs("__forceinline ", out);
1208                 else
1209                         fputs("inline ", out);
1210         }
1211         print_type_ext(declaration->type, declaration->symbol,
1212                        &declaration->scope);
1213
1214         if(declaration->type->kind == TYPE_FUNCTION) {
1215                 if(declaration->init.statement != NULL) {
1216                         fputs("\n", out);
1217                         print_statement(declaration->init.statement);
1218                         return;
1219                 }
1220         } else if(declaration->init.initializer != NULL) {
1221                 fputs(" = ", out);
1222                 print_initializer(declaration->init.initializer);
1223         }
1224         fputc(';', out);
1225 }
1226
1227 /**
1228  * Prints an expression.
1229  *
1230  * @param expression  the expression
1231  */
1232 void print_expression(const expression_t *expression) {
1233         print_expression_prec(expression, PREC_BOTTOM);
1234 }
1235
1236 /**
1237  * Print a declaration.
1238  *
1239  * @param declaration  the declaration
1240  */
1241 void print_declaration(const declaration_t *declaration)
1242 {
1243         if(declaration->namespc != NAMESPACE_NORMAL &&
1244                         declaration->symbol == NULL)
1245                 return;
1246
1247         switch(declaration->namespc) {
1248         case NAMESPACE_NORMAL:
1249                 print_normal_declaration(declaration);
1250                 break;
1251         case NAMESPACE_STRUCT:
1252                 fputs("struct ", out);
1253                 fputs(declaration->symbol->string, out);
1254                 fputc(' ', out);
1255                 print_compound_definition(declaration);
1256                 fputc(';', out);
1257                 break;
1258         case NAMESPACE_UNION:
1259                 fputs("union ", out);
1260                 fputs(declaration->symbol->string, out);
1261                 fputc(' ', out);
1262                 print_compound_definition(declaration);
1263                 fputc(';', out);
1264                 break;
1265         case NAMESPACE_ENUM:
1266                 fputs("enum ", out);
1267                 fputs(declaration->symbol->string, out);
1268                 fputc(' ', out);
1269                 print_enum_definition(declaration);
1270                 fputc(';', out);
1271                 break;
1272         }
1273 }
1274
1275 /**
1276  * Print the AST of a translation unit.
1277  *
1278  * @param unit   the translation unit
1279  */
1280 void print_ast(const translation_unit_t *unit)
1281 {
1282         inc_type_visited();
1283
1284         declaration_t *declaration = unit->scope.declarations;
1285         for( ; declaration != NULL; declaration = declaration->next) {
1286                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
1287                         continue;
1288                 if(declaration->namespc != NAMESPACE_NORMAL &&
1289                                 declaration->symbol == NULL)
1290                         continue;
1291
1292                 print_indent();
1293                 print_declaration(declaration);
1294                 fputc('\n', out);
1295         }
1296 }
1297
1298 bool is_constant_initializer(const initializer_t *initializer)
1299 {
1300         switch(initializer->kind) {
1301         case INITIALIZER_STRING:
1302         case INITIALIZER_WIDE_STRING:
1303         case INITIALIZER_DESIGNATOR:
1304                 return true;
1305
1306         case INITIALIZER_VALUE:
1307                 return is_constant_expression(initializer->value.value);
1308
1309         case INITIALIZER_LIST: {
1310                 for(size_t i = 0; i < initializer->list.len; ++i) {
1311                         initializer_t *sub_initializer = initializer->list.initializers[i];
1312                         if(!is_constant_initializer(sub_initializer))
1313                                 return false;
1314                 }
1315                 return true;
1316         }
1317         }
1318         panic("invalid initializer kind found");
1319 }
1320
1321 static bool is_object_with_constant_address(const expression_t *expression)
1322 {
1323         switch(expression->kind) {
1324         case EXPR_UNARY_DEREFERENCE:
1325                 return is_address_constant(expression->unary.value);
1326
1327         case EXPR_SELECT: {
1328                 if(is_type_pointer(expression->select.compound->base.type)) {
1329                         /* it's a -> */
1330                         return is_address_constant(expression->select.compound);
1331                 } else {
1332                         return is_object_with_constant_address(expression->select.compound);
1333                 }
1334         }
1335
1336         case EXPR_ARRAY_ACCESS:
1337                 return is_constant_expression(expression->array_access.index)
1338                         && is_address_constant(expression->array_access.array_ref);
1339
1340         case EXPR_REFERENCE: {
1341                 declaration_t *declaration = expression->reference.declaration;
1342                 switch((storage_class_tag_t) declaration->storage_class) {
1343                 case STORAGE_CLASS_NONE:
1344                 case STORAGE_CLASS_EXTERN:
1345                 case STORAGE_CLASS_STATIC:
1346                         return true;
1347                 default:
1348                         return false;
1349                 }
1350         }
1351
1352         default:
1353                 return false;
1354         }
1355 }
1356
1357 bool is_address_constant(const expression_t *expression)
1358 {
1359         switch(expression->kind) {
1360         case EXPR_UNARY_TAKE_ADDRESS:
1361                 return is_object_with_constant_address(expression->unary.value);
1362
1363         case EXPR_UNARY_CAST:
1364                 return is_type_pointer(skip_typeref(expression->base.type))
1365                         && (is_constant_expression(expression->unary.value)
1366                         || is_address_constant(expression->unary.value));
1367
1368         case EXPR_BINARY_ADD:
1369         case EXPR_BINARY_SUB: {
1370                 expression_t *left  = expression->binary.left;
1371                 expression_t *right = expression->binary.right;
1372
1373                 if(is_type_pointer(skip_typeref(left->base.type))) {
1374                         return is_address_constant(left) && is_constant_expression(right);
1375                 } else if(is_type_pointer(skip_typeref(right->base.type))) {
1376                         return is_constant_expression(left)     && is_address_constant(right);
1377                 }
1378
1379                 return false;
1380         }
1381
1382         case EXPR_REFERENCE: {
1383                 declaration_t *declaration = expression->reference.declaration;
1384                 type_t *type = skip_typeref(declaration->type);
1385                 if(is_type_function(type))
1386                         return true;
1387                 if(is_type_array(type)) {
1388                         return is_object_with_constant_address(expression);
1389                 }
1390                 return false;
1391         }
1392
1393         default:
1394                 return false;
1395         }
1396 }
1397
1398 bool is_constant_expression(const expression_t *expression)
1399 {
1400         switch(expression->kind) {
1401
1402         case EXPR_CONST:
1403         case EXPR_CHAR_CONST:
1404         case EXPR_STRING_LITERAL:
1405         case EXPR_WIDE_STRING_LITERAL:
1406         case EXPR_SIZEOF:
1407         case EXPR_CLASSIFY_TYPE:
1408         case EXPR_FUNCTION:
1409         case EXPR_PRETTY_FUNCTION:
1410         case EXPR_OFFSETOF:
1411         case EXPR_ALIGNOF:
1412         case EXPR_BUILTIN_CONSTANT_P:
1413                 return true;
1414
1415         case EXPR_BUILTIN_SYMBOL:
1416         case EXPR_BUILTIN_PREFETCH:
1417         case EXPR_CALL:
1418         case EXPR_SELECT:
1419         case EXPR_VA_START:
1420         case EXPR_VA_ARG:
1421         case EXPR_STATEMENT:
1422         case EXPR_UNARY_POSTFIX_INCREMENT:
1423         case EXPR_UNARY_POSTFIX_DECREMENT:
1424         case EXPR_UNARY_PREFIX_INCREMENT:
1425         case EXPR_UNARY_PREFIX_DECREMENT:
1426         case EXPR_UNARY_BITFIELD_EXTRACT:
1427         case EXPR_UNARY_ASSUME: /* has VOID type */
1428         case EXPR_UNARY_DEREFERENCE:
1429         case EXPR_UNARY_TAKE_ADDRESS:
1430         case EXPR_BINARY_ASSIGN:
1431         case EXPR_BINARY_MUL_ASSIGN:
1432         case EXPR_BINARY_DIV_ASSIGN:
1433         case EXPR_BINARY_MOD_ASSIGN:
1434         case EXPR_BINARY_ADD_ASSIGN:
1435         case EXPR_BINARY_SUB_ASSIGN:
1436         case EXPR_BINARY_SHIFTLEFT_ASSIGN:
1437         case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
1438         case EXPR_BINARY_BITWISE_AND_ASSIGN:
1439         case EXPR_BINARY_BITWISE_XOR_ASSIGN:
1440         case EXPR_BINARY_BITWISE_OR_ASSIGN:
1441         case EXPR_BINARY_COMMA:
1442                 return false;
1443
1444         case EXPR_UNARY_NEGATE:
1445         case EXPR_UNARY_PLUS:
1446         case EXPR_UNARY_BITWISE_NEGATE:
1447         case EXPR_UNARY_NOT:
1448                 return is_constant_expression(expression->unary.value);
1449
1450         case EXPR_UNARY_CAST:
1451         case EXPR_UNARY_CAST_IMPLICIT:
1452                 return is_type_arithmetic(skip_typeref(expression->base.type))
1453                         && is_constant_expression(expression->unary.value);
1454
1455         case EXPR_BINARY_ADD:
1456         case EXPR_BINARY_SUB:
1457         case EXPR_BINARY_MUL:
1458         case EXPR_BINARY_DIV:
1459         case EXPR_BINARY_MOD:
1460         case EXPR_BINARY_EQUAL:
1461         case EXPR_BINARY_NOTEQUAL:
1462         case EXPR_BINARY_LESS:
1463         case EXPR_BINARY_LESSEQUAL:
1464         case EXPR_BINARY_GREATER:
1465         case EXPR_BINARY_GREATEREQUAL:
1466         case EXPR_BINARY_BITWISE_AND:
1467         case EXPR_BINARY_BITWISE_OR:
1468         case EXPR_BINARY_BITWISE_XOR:
1469         case EXPR_BINARY_LOGICAL_AND:
1470         case EXPR_BINARY_LOGICAL_OR:
1471         case EXPR_BINARY_SHIFTLEFT:
1472         case EXPR_BINARY_SHIFTRIGHT:
1473         case EXPR_BINARY_BUILTIN_EXPECT:
1474         case EXPR_BINARY_ISGREATER:
1475         case EXPR_BINARY_ISGREATEREQUAL:
1476         case EXPR_BINARY_ISLESS:
1477         case EXPR_BINARY_ISLESSEQUAL:
1478         case EXPR_BINARY_ISLESSGREATER:
1479         case EXPR_BINARY_ISUNORDERED:
1480                 return is_constant_expression(expression->binary.left)
1481                         && is_constant_expression(expression->binary.right);
1482
1483         case EXPR_COMPOUND_LITERAL:
1484                 return is_constant_initializer(expression->compound_literal.initializer);
1485
1486         case EXPR_CONDITIONAL: {
1487                 expression_t *condition = expression->conditional.condition;
1488                 if(!is_constant_expression(condition))
1489                         return false;
1490
1491                 long val = fold_constant(condition);
1492                 if(val != 0)
1493                         return is_constant_expression(expression->conditional.true_expression);
1494                 else
1495                         return is_constant_expression(expression->conditional.false_expression);
1496         }
1497
1498         case EXPR_ARRAY_ACCESS:
1499                 return is_constant_expression(expression->array_access.array_ref)
1500                         && is_constant_expression(expression->array_access.index);
1501
1502         case EXPR_REFERENCE: {
1503                 declaration_t *declaration = expression->reference.declaration;
1504                 if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
1505                         return true;
1506
1507                 return false;
1508         }
1509
1510         case EXPR_UNKNOWN:
1511         case EXPR_INVALID:
1512                 break;
1513         }
1514         panic("invalid expression found (is constant expression)");
1515 }
1516
1517 /**
1518  * Initialize the AST construction.
1519  */
1520 void init_ast(void)
1521 {
1522         obstack_init(&ast_obstack);
1523 }
1524
1525 /**
1526  * Free the AST.
1527  */
1528 void exit_ast(void)
1529 {
1530         obstack_free(&ast_obstack, NULL);
1531 }
1532
1533 /**
1534  * Set the output stream for the AST printer.
1535  *
1536  * @param stream  the output stream
1537  */
1538 void ast_set_output(FILE *stream)
1539 {
1540         out = stream;
1541         type_set_output(stream);
1542 }
1543
1544 /**
1545  * Allocate an AST object of the given size.
1546  *
1547  * @param size  the size of the object to allocate
1548  *
1549  * @return  A new allocated object in the AST memeory space.
1550  */
1551 void *(allocate_ast)(size_t size)
1552 {
1553         return _allocate_ast(size);
1554 }