type: Make an assert()ion independent of the last entry of an enum.
[cparser] / walk.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
4  */
5 #include <config.h>
6
7 #include "adt/error.h"
8 #include "ast_t.h"
9 #include "entity_t.h"
10 #include "type_t.h"
11 #include "walk.h"
12 #include <libfirm/adt/pset.h>
13
14 typedef struct walk_env_t {
15         pset *visited_types;
16         declaration_callback declaration_func;
17         statement_callback   statement_func;
18         expression_callback  expression_func;
19         void *env;
20 } walk_env_t;
21
22 static void walk_expression(expression_t *expr, const walk_env_t *const env);
23 static void walk_statement(statement_t *stmt, const walk_env_t *env);
24 static void walk_entity(entity_t *entity, const walk_env_t *env);
25 static void walk_designator(const designator_t *, const walk_env_t *);
26 static void walk_initializer(const initializer_t  *, const walk_env_t *);
27 static void walk_scope(const scope_t *const scope, const walk_env_t *const env);
28
29 static void walk_type(type_t *const type, const walk_env_t *const env)
30 {
31         if (pset_find_ptr(env->visited_types, type) != NULL)
32                 return;
33         pset_insert_ptr(env->visited_types, type);
34
35         switch (type->kind) {
36         case TYPE_ATOMIC:
37         case TYPE_COMPLEX:
38         case TYPE_IMAGINARY:
39         case TYPE_REFERENCE:
40         case TYPE_ERROR:
41                 return;
42         case TYPE_POINTER:
43                 walk_type(type->pointer.points_to, env);
44                 return;
45         case TYPE_ARRAY:
46                 walk_type(type->array.element_type, env);
47                 if (type->array.size_expression != NULL)
48                         walk_expression(type->array.size_expression, env);
49                 return;
50         case TYPE_FUNCTION:
51                 for (function_parameter_t *parameter = type->function.parameters;
52                      parameter != NULL; parameter = parameter->next) {
53                         walk_type(parameter->type, env);
54                 }
55                 walk_type(type->function.return_type, env);
56                 return;
57         case TYPE_TYPEOF:
58                 walk_expression(type->typeoft.expression, env);
59                 return;
60         case TYPE_TYPEDEF:
61                 walk_entity((entity_t*)type->typedeft.typedefe, env);
62                 return;
63         case TYPE_COMPOUND_STRUCT:
64         case TYPE_COMPOUND_UNION:
65                 walk_entity((entity_t*)type->compound.compound, env);
66                 return;
67         case TYPE_ENUM:
68                 walk_entity((entity_t*)type->enumt.enume, env);
69                 return;
70         }
71         panic("invalid type");
72 }
73
74 static void walk_expression(expression_t *const expr,
75                             const walk_env_t *const env)
76 {
77         env->expression_func(expr, env->env);
78
79         switch (expr->base.kind) {
80         case EXPR_STATEMENT:
81                 walk_statement(expr->statement.statement, env);
82                 return;
83
84         case EXPR_BINARY_CASES:
85                 walk_expression(expr->binary.left, env);
86                 walk_expression(expr->binary.right, env);
87                 return;
88
89         case EXPR_UNARY_CASES_OPTIONAL:
90                 if (expr->unary.value == NULL)
91                         return;
92                 /* FALLTHROUGH */
93         case EXPR_UNARY_CASES_MANDATORY:
94                 walk_expression(expr->unary.value, env);
95                 return;
96
97         case EXPR_CALL:
98                 for (call_argument_t *arg = expr->call.arguments; arg != NULL;
99                      arg = arg->next) {
100                         walk_expression(arg->expression, env);
101                 }
102                 return;
103
104         case EXPR_COMPOUND_LITERAL:
105                 walk_initializer(expr->compound_literal.initializer, env);
106                 return;
107
108         case EXPR_CONDITIONAL:
109                 walk_expression(expr->conditional.condition, env);
110                 /* may be NULL because of gnu extension */
111                 if (expr->conditional.true_expression != NULL)
112                         walk_expression(expr->conditional.true_expression, env);
113                 walk_expression(expr->conditional.false_expression, env);
114                 return;
115
116         case EXPR_BUILTIN_CONSTANT_P:
117                 walk_expression(expr->builtin_constant.value, env);
118                 return;
119
120         case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
121                 walk_type(expr->builtin_types_compatible.left, env);
122                 walk_type(expr->builtin_types_compatible.right, env);
123                 return;
124
125         case EXPR_SELECT:
126                 walk_expression(expr->select.compound, env);
127                 return;
128
129         case EXPR_ARRAY_ACCESS:
130                 walk_expression(expr->array_access.array_ref, env);
131                 walk_expression(expr->array_access.index, env);
132                 return;
133
134         case EXPR_CLASSIFY_TYPE:
135                 walk_expression(expr->classify_type.type_expression, env);
136                 return;
137
138         case EXPR_SIZEOF:
139         case EXPR_ALIGNOF: {
140                 expression_t *tp_expression = expr->typeprop.tp_expression;
141                 if (tp_expression != NULL) {
142                         walk_expression(tp_expression, env);
143                 }
144                 return;
145         }
146
147         case EXPR_VA_START:
148                 walk_expression(expr->va_starte.ap, env);
149                 return;
150
151         case EXPR_VA_ARG:
152                 walk_expression(expr->va_arge.ap, env);
153                 return;
154
155         case EXPR_VA_COPY:
156                 walk_expression(expr->va_copye.src, env);
157                 walk_expression(expr->va_copye.dst, env);
158                 return;
159
160         case EXPR_OFFSETOF:
161                 walk_designator(expr->offsetofe.designator, env);
162                 return;
163
164         case EXPR_LITERAL_CASES:
165         case EXPR_LITERAL_CHARACTER:
166         case EXPR_REFERENCE:
167         case EXPR_ENUM_CONSTANT:
168         case EXPR_STRING_LITERAL:
169         case EXPR_FUNCNAME:
170         case EXPR_LABEL_ADDRESS:
171         case EXPR_ERROR:
172                 return;
173         }
174         panic("invalid expr kind");
175 }
176
177 static void walk_designator(const designator_t *designator,
178                             const walk_env_t *const env)
179 {
180         for ( ; designator != NULL; designator = designator->next) {
181                 if (designator->array_index != NULL)
182                         walk_expression(designator->array_index, env);
183         }
184 }
185
186 static void walk_initializer(const initializer_t  *initializer,
187                              const walk_env_t *const env)
188 {
189         switch (initializer->kind) {
190         case INITIALIZER_VALUE:
191                 walk_expression(initializer->value.value, env);
192                 return;
193         case INITIALIZER_LIST: {
194                 for (size_t i = 0; i < initializer->list.len; ++i) {
195                         walk_initializer(initializer->list.initializers[i], env);
196                 }
197                 return;
198         }
199         case INITIALIZER_DESIGNATOR:
200                 walk_designator(initializer->designator.designator, env);
201                 return;
202
203         case INITIALIZER_STRING:
204                 return;
205         }
206 }
207
208 static void walk_entity(entity_t *entity, const walk_env_t *const env)
209 {
210         env->declaration_func(entity, env->env);
211
212         switch (entity->kind) {
213         case ENTITY_VARIABLE: {
214                 const variable_t    *variable    = &entity->variable;
215                 const initializer_t *initializer = variable->initializer;
216                 walk_type(entity->declaration.type, env);
217                 if (initializer != NULL) {
218                         walk_initializer(initializer, env);
219                 }
220                 return;
221         }
222         case ENTITY_ENUM_VALUE:
223                 if (entity->enum_value.value != NULL)
224                         walk_expression(entity->enum_value.value, env);
225                 return;
226         case ENTITY_TYPEDEF:
227                 walk_type(entity->typedefe.type, env);
228                 return;
229         case ENTITY_FUNCTION:
230                 walk_type(entity->declaration.type, env);
231                 if (entity->function.body != NULL)
232                         walk_statement(entity->function.body, env);
233                 return;
234         case ENTITY_COMPOUND_MEMBER:
235         case ENTITY_PARAMETER:
236                 walk_type(entity->declaration.type, env);
237                 return;
238         case ENTITY_CLASS:
239         case ENTITY_STRUCT:
240         case ENTITY_UNION:
241                 walk_scope(&entity->compound.members, env);
242                 return;
243         case ENTITY_NAMESPACE:
244                 walk_scope(&entity->namespacee.members, env);
245                 return;
246         case ENTITY_ENUM:
247                 for (entity = entity->base.next;
248                      entity != NULL && entity->kind == ENTITY_ENUM_VALUE;
249                          entity = entity->base.next) {
250                         walk_entity(entity, env);
251                 }
252                 return;
253         case ENTITY_LABEL:
254         case ENTITY_LOCAL_LABEL:
255                 return;
256         }
257         panic("invalid entity");
258 }
259
260 static void walk_declarations(entity_t*            entity,
261                               entity_t*      const last,
262                                                           const walk_env_t    *const env)
263 {
264         entity_t const *const end = last != NULL ? last->base.next : NULL;
265         for (; entity != end; entity = entity->base.next) {
266                 walk_entity(entity, env);
267         }
268 }
269
270 static void walk_scope(const scope_t *const scope, const walk_env_t *const env)
271 {
272         walk_declarations(scope->entities, NULL, env);
273 }
274
275 static void walk_statement(statement_t *const stmt, const walk_env_t *const env)
276 {
277         env->statement_func(stmt, env->env);
278
279         switch (stmt->kind) {
280         case STATEMENT_COMPOUND:
281                 for (statement_t *s = stmt->compound.statements; s != NULL;
282                      s = s->base.next) {
283                         walk_statement(s, env);
284                 }
285                 return;
286
287         case STATEMENT_FOR:
288                 walk_declarations(stmt->fors.scope.entities, NULL, env);
289                 if (stmt->fors.initialisation != NULL)
290                         walk_expression(stmt->fors.initialisation, env);
291                 if (stmt->fors.condition != NULL)
292                         walk_expression(stmt->fors.condition, env);
293                 if (stmt->fors.step != NULL)
294                         walk_expression(stmt->fors.step, env);
295                 walk_statement(stmt->fors.body, env);
296                 return;
297
298         case STATEMENT_IF:
299                 walk_expression(stmt->ifs.condition, env);
300                 walk_statement(stmt->ifs.true_statement, env);
301                 if (stmt->ifs.false_statement != NULL)
302                         walk_statement(stmt->ifs.false_statement, env);
303                 return;
304
305         case STATEMENT_SWITCH:
306                 walk_expression(stmt->switchs.expression, env);
307                 walk_statement(stmt->switchs.body, env);
308                 return;
309
310         case STATEMENT_LABEL:
311                 walk_statement(stmt->label.statement, env);
312                 return;
313
314         case STATEMENT_CASE_LABEL:
315                 if (stmt->case_label.expression) {
316                         walk_expression(stmt->case_label.expression, env);
317                         if (stmt->case_label.end_range)
318                                 walk_expression(stmt->case_label.end_range, env);
319                 }
320                 walk_statement(stmt->case_label.statement, env);
321                 return;
322
323         case STATEMENT_DO_WHILE:
324                 walk_statement(stmt->do_while.body, env);
325                 walk_expression(stmt->do_while.condition, env);
326                 return;
327
328         case STATEMENT_EXPRESSION:
329                 walk_expression(stmt->expression.expression, env);
330                 return;
331
332         case STATEMENT_RETURN:
333                 if (stmt->returns.value != NULL)
334                         walk_expression(stmt->returns.value, env);
335                 return;
336
337         case STATEMENT_DECLARATION:
338                 walk_declarations(stmt->declaration.declarations_begin,
339                                 stmt->declaration.declarations_end, env);
340                 return;
341
342         case STATEMENT_MS_TRY:
343                 walk_statement(stmt->ms_try.try_statement, env);
344                 walk_statement(stmt->ms_try.final_statement, env);
345                 return;
346
347         case STATEMENT_COMPUTED_GOTO:
348                 walk_expression(stmt->computed_goto.expression, env);
349                 return;
350
351         case STATEMENT_ERROR:
352         case STATEMENT_EMPTY:
353         case STATEMENT_CONTINUE:
354         case STATEMENT_BREAK:
355         case STATEMENT_ASM:
356         case STATEMENT_GOTO:
357         case STATEMENT_LEAVE:
358                 return;
359         }
360
361         panic("unhandled statement");
362 }
363
364 static void null_declaration_func(entity_t *entity, void *env)
365 {
366         (void) entity;
367         (void) env;
368 }
369
370 static void null_statement_func(statement_t *statement, void *env)
371 {
372         (void) statement;
373         (void) env;
374 }
375
376 static void null_expression_func(expression_t *expression, void *env)
377 {
378         (void) expression;
379         (void) env;
380 }
381
382 void walk_translation_unit(translation_unit_t *unit,
383                            declaration_callback declaration_func,
384                                                    statement_callback statement_func,
385                                                    expression_callback expression_func, void *env)
386 {
387         walk_env_t walk_env = {
388                 pset_new_ptr_default(),
389                 declaration_func != NULL ? declaration_func : null_declaration_func,
390                 statement_func != NULL ? statement_func : null_statement_func,
391                 expression_func != NULL ? expression_func : null_expression_func,
392                 env
393         };
394         walk_scope(&unit->scope, &walk_env);
395         del_pset(walk_env.visited_types);
396 }
397
398 void walk_statements(statement_t *statement, statement_callback func, void *env)
399 {
400         walk_env_t walk_env
401                 = { pset_new_ptr_default(),
402                     null_declaration_func, func, null_expression_func, env };
403         walk_statement(statement, &walk_env);
404         del_pset(walk_env.visited_types);
405 }