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