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