Parse and check semantic of throw expressions.
[cparser] / walk_statements.c
1 #include "adt/error.h"
2 #include "ast_t.h"
3 #include "walk_statements.h"
4
5
6 static void walk_expression(expression_t const *const expr, statement_callback const callback, void *const env)
7 {
8         switch (expr->base.kind) {
9                 case EXPR_STATEMENT:
10                         walk_statements(expr->statement.statement, callback, env);
11                         return;
12
13                 EXPR_BINARY_CASES
14                         walk_expression(expr->binary.left,  callback, env);
15                         walk_expression(expr->binary.right, callback, env);
16                         return;
17
18                 EXPR_UNARY_CASES_OPTIONAL
19                         if (expr->unary.value == NULL)
20                                 return;
21                         /* FALLTHROUGH */
22                 EXPR_UNARY_CASES_MANDATORY
23                         walk_expression(expr->unary.value, callback, env);
24                         return;
25
26                 case EXPR_CALL:
27                         for (call_argument_t *arg = expr->call.arguments; arg != NULL; arg = arg->next) {
28                                 walk_expression(arg->expression, callback, env);
29                         }
30                         return;
31
32                 case EXPR_UNKNOWN:
33                 case EXPR_INVALID:
34                         panic("unexpected expr kind");
35
36                 case EXPR_COMPOUND_LITERAL:
37                         /* TODO... */
38                         break;
39
40                 case EXPR_CONDITIONAL:
41                         walk_expression(expr->conditional.condition,        callback, env);
42                         walk_expression(expr->conditional.true_expression,  callback, env);
43                         walk_expression(expr->conditional.false_expression, callback, env);
44                         return;
45
46                 case EXPR_BUILTIN_PREFETCH:
47                         walk_expression(expr->builtin_prefetch.adr,      callback, env);
48                         walk_expression(expr->builtin_prefetch.rw,       callback, env);
49                         walk_expression(expr->builtin_prefetch.locality, callback, env);
50                         return;
51
52                 case EXPR_BUILTIN_CONSTANT_P:
53                         walk_expression(expr->builtin_constant.value, callback, env);
54                         return;
55
56                 case EXPR_SELECT:
57                         walk_expression(expr->select.compound, callback, env);
58                         return;
59
60                 case EXPR_ARRAY_ACCESS:
61                         walk_expression(expr->array_access.array_ref, callback, env);
62                         walk_expression(expr->array_access.index,     callback, env);
63                         return;
64
65                 case EXPR_CLASSIFY_TYPE:
66                         walk_expression(expr->classify_type.type_expression, callback, env);
67                         return;
68
69                 case EXPR_SIZEOF:
70                 case EXPR_ALIGNOF: {
71                         expression_t *tp_expression = expr->typeprop.tp_expression;
72                         if (tp_expression != NULL) {
73                                 walk_expression(tp_expression, callback, env);
74                         }
75                         return;
76                 }
77
78                 case EXPR_OFFSETOF:
79                 case EXPR_REFERENCE:
80                 case EXPR_CONST:
81                 case EXPR_CHARACTER_CONSTANT:
82                 case EXPR_WIDE_CHARACTER_CONSTANT:
83                 case EXPR_STRING_LITERAL:
84                 case EXPR_WIDE_STRING_LITERAL:
85                 case EXPR_FUNCNAME:
86                 case EXPR_BUILTIN_SYMBOL:
87                 case EXPR_VA_START:
88                 case EXPR_VA_ARG:
89                 case EXPR_LABEL_ADDRESS:
90                         break;
91         }
92
93         /* TODO FIXME: implement all the missing expressions here */
94 }
95
96
97 static void walk_declarations(const declaration_t *      decl,
98                               const declaration_t *const end,
99                               statement_callback   const callback,
100                               void                *const env)
101 {
102         for (; decl != end; decl = decl->next) {
103                 if (decl->namespc != NAMESPACE_NORMAL)
104                         continue;
105
106                 const initializer_t *initializer = decl->init.initializer;
107                 /* FIXME: should walk initializer hierarchies... */
108                 if (initializer != NULL && initializer->kind == INITIALIZER_VALUE) {
109                         walk_expression(initializer->value.value, callback, env);
110                 }
111         }
112 }
113
114
115 void walk_statements(statement_t *const stmt, statement_callback const callback, void *const env)
116 {
117         callback(stmt, env);
118
119         switch (stmt->kind) {
120                 case STATEMENT_COMPOUND:
121                         for (statement_t *s = stmt->compound.statements; s != NULL; s = s->base.next) {
122                                 walk_statements(s, callback, env);
123                         }
124                         return;
125
126                 case STATEMENT_FOR:
127                         walk_declarations(stmt->fors.scope.declarations, NULL, callback, env);
128                         if (stmt->fors.initialisation != NULL)
129                                 walk_expression(stmt->fors.initialisation, callback, env);
130                         if (stmt->fors.condition != NULL)
131                                 walk_expression(stmt->fors.condition, callback, env);
132                         if (stmt->fors.step != NULL)
133                                 walk_expression(stmt->fors.step, callback, env);
134                         walk_statements(stmt->fors.body,           callback, env);
135                         return;
136
137                 case STATEMENT_IF:
138                         walk_expression(stmt->ifs.condition,      callback, env);
139                         walk_statements(stmt->ifs.true_statement, callback, env);
140                         if (stmt->ifs.false_statement != NULL)
141                                 walk_statements(stmt->ifs.false_statement, callback, env);
142                         return;
143
144                 case STATEMENT_SWITCH:
145                         walk_expression(stmt->switchs.expression, callback, env);
146                         walk_statements(stmt->switchs.body,       callback, env);
147                         return;
148
149                 case STATEMENT_LABEL:
150                         walk_statements(stmt->label.statement, callback, env);
151                         return;
152
153                 case STATEMENT_CASE_LABEL:
154                         walk_statements(stmt->case_label.statement, callback, env);
155                         return;
156
157                 case STATEMENT_WHILE:
158                         walk_expression(stmt->whiles.condition, callback, env);
159                         walk_statements(stmt->whiles.body,      callback, env);
160                         return;
161
162                 case STATEMENT_DO_WHILE:
163                         walk_statements(stmt->do_while.body,      callback, env);
164                         walk_expression(stmt->do_while.condition, callback, env);
165                         return;
166
167                 case STATEMENT_EXPRESSION:
168                         walk_expression(stmt->expression.expression, callback, env);
169                         return;
170
171                 case STATEMENT_RETURN:
172                         if (stmt->returns.value != NULL)
173                                 walk_expression(stmt->returns.value, callback, env);
174                         return;
175
176                 case STATEMENT_DECLARATION:
177                         walk_declarations(stmt->declaration.declarations_begin,
178                                           stmt->declaration.declarations_end->next,
179                                           callback, env);
180                         return;
181
182                 case STATEMENT_MS_TRY:
183                         walk_statements(stmt->ms_try.try_statement,   callback, env);
184                         walk_statements(stmt->ms_try.final_statement, callback, env);
185                         return;
186
187                 case STATEMENT_INVALID:
188                 case STATEMENT_EMPTY:
189                 case STATEMENT_CONTINUE:
190                 case STATEMENT_BREAK:
191                 case STATEMENT_GOTO:
192                 case STATEMENT_ASM:
193                 case STATEMENT_LEAVE:
194                         return;
195         }
196
197         panic("unhandled statement");
198 }