2 * This file is part of cparser.
3 * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
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.
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.
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
22 #include "adt/error.h"
27 #include <libfirm/adt/pset.h>
29 typedef struct walk_env_t {
31 declaration_callback declaration_func;
32 statement_callback statement_func;
33 expression_callback expression_func;
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);
44 static void walk_type(type_t *const type, const walk_env_t *const env)
46 if (pset_find_ptr(env->visited_types, type) != NULL)
48 pset_insert_ptr(env->visited_types, type);
58 walk_type(type->pointer.points_to, env);
61 walk_type(type->array.element_type, env);
62 if (type->array.size_expression != NULL)
63 walk_expression(type->array.size_expression, env);
66 for (function_parameter_t *parameter = type->function.parameters;
67 parameter != NULL; parameter = parameter->next) {
68 walk_type(parameter->type, env);
70 walk_type(type->function.return_type, env);
73 walk_expression(type->typeoft.expression, env);
76 walk_entity((entity_t*)type->typedeft.typedefe, env);
78 case TYPE_COMPOUND_STRUCT:
79 case TYPE_COMPOUND_UNION:
80 walk_entity((entity_t*)type->compound.compound, env);
83 walk_entity((entity_t*)type->enumt.enume, env);
88 panic("invalid type found");
91 static void walk_expression(expression_t *const expr,
92 const walk_env_t *const env)
94 env->expression_func(expr, env->env);
96 switch (expr->base.kind) {
98 walk_statement(expr->statement.statement, env);
102 walk_expression(expr->binary.left, env);
103 walk_expression(expr->binary.right, env);
106 EXPR_UNARY_CASES_OPTIONAL
107 if (expr->unary.value == NULL)
110 EXPR_UNARY_CASES_MANDATORY
111 walk_expression(expr->unary.value, env);
115 for (call_argument_t *arg = expr->call.arguments; arg != NULL;
117 walk_expression(arg->expression, env);
121 case EXPR_COMPOUND_LITERAL:
122 walk_initializer(expr->compound_literal.initializer, env);
125 case EXPR_CONDITIONAL:
126 walk_expression(expr->conditional.condition, env);
127 /* may be NULL because of gnu extension */
128 if (expr->conditional.true_expression != NULL)
129 walk_expression(expr->conditional.true_expression, env);
130 walk_expression(expr->conditional.false_expression, env);
133 case EXPR_BUILTIN_CONSTANT_P:
134 walk_expression(expr->builtin_constant.value, env);
137 case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
138 walk_type(expr->builtin_types_compatible.left, env);
139 walk_type(expr->builtin_types_compatible.right, env);
143 walk_expression(expr->select.compound, env);
146 case EXPR_ARRAY_ACCESS:
147 walk_expression(expr->array_access.array_ref, env);
148 walk_expression(expr->array_access.index, env);
151 case EXPR_CLASSIFY_TYPE:
152 walk_expression(expr->classify_type.type_expression, env);
157 expression_t *tp_expression = expr->typeprop.tp_expression;
158 if (tp_expression != NULL) {
159 walk_expression(tp_expression, env);
165 walk_expression(expr->va_starte.ap, env);
169 walk_expression(expr->va_arge.ap, env);
173 walk_expression(expr->va_copye.src, env);
174 walk_expression(expr->va_copye.dst, env);
178 walk_designator(expr->offsetofe.designator, env);
183 case EXPR_REFERENCE_ENUM_VALUE:
184 case EXPR_STRING_LITERAL:
185 case EXPR_WIDE_STRING_LITERAL:
187 case EXPR_LABEL_ADDRESS:
192 panic("invalid expr kind");
195 static void walk_designator(const designator_t *designator,
196 const walk_env_t *const env)
198 for ( ; designator != NULL; designator = designator->next) {
199 if (designator->array_index != NULL)
200 walk_expression(designator->array_index, env);
204 static void walk_initializer(const initializer_t *initializer,
205 const walk_env_t *const env)
207 switch(initializer->kind) {
208 case INITIALIZER_VALUE:
209 walk_expression(initializer->value.value, env);
211 case INITIALIZER_LIST: {
212 for (size_t i = 0; i < initializer->list.len; ++i) {
213 walk_initializer(initializer->list.initializers[i], env);
217 case INITIALIZER_DESIGNATOR:
218 walk_designator(initializer->designator.designator, env);
220 case INITIALIZER_STRING:
221 case INITIALIZER_WIDE_STRING:
226 static void walk_entity(entity_t *entity, const walk_env_t *const env)
228 env->declaration_func(entity, env->env);
230 switch (entity->kind) {
231 case ENTITY_VARIABLE: {
232 const variable_t *variable = &entity->variable;
233 const initializer_t *initializer = variable->initializer;
234 walk_type(entity->declaration.type, env);
235 if (initializer != NULL) {
236 walk_initializer(initializer, env);
240 case ENTITY_ENUM_VALUE:
241 if (entity->enum_value.value != NULL)
242 walk_expression(entity->enum_value.value, env);
245 walk_type(entity->typedefe.type, env);
247 case ENTITY_FUNCTION:
248 walk_type(entity->declaration.type, env);
249 if (entity->function.statement != NULL)
250 walk_statement(entity->function.statement, env);
252 case ENTITY_COMPOUND_MEMBER:
253 case ENTITY_PARAMETER:
254 walk_type(entity->declaration.type, env);
259 walk_scope(&entity->compound.members, env);
261 case ENTITY_NAMESPACE:
262 walk_scope(&entity->namespacee.members, env);
265 for (entity = entity->base.next;
266 entity != NULL && entity->kind == ENTITY_ENUM_VALUE;
267 entity = entity->base.next) {
268 walk_entity(entity, env);
272 case ENTITY_LOCAL_LABEL:
277 panic("invalid entity found");
280 static void walk_declarations(entity_t* entity,
281 entity_t* const last,
282 const walk_env_t *const env)
284 entity_t const *const end = last != NULL ? last->base.next : NULL;
285 for (; entity != end; entity = entity->base.next) {
286 walk_entity(entity, env);
290 static void walk_scope(const scope_t *const scope, const walk_env_t *const env)
292 walk_declarations(scope->entities, NULL, env);
295 static void walk_statement(statement_t *const stmt, const walk_env_t *const env)
297 env->statement_func(stmt, env->env);
299 switch (stmt->kind) {
300 case STATEMENT_COMPOUND:
301 for (statement_t *s = stmt->compound.statements; s != NULL;
303 walk_statement(s, env);
308 walk_declarations(stmt->fors.scope.entities, NULL, env);
309 if (stmt->fors.initialisation != NULL)
310 walk_expression(stmt->fors.initialisation, env);
311 if (stmt->fors.condition != NULL)
312 walk_expression(stmt->fors.condition, env);
313 if (stmt->fors.step != NULL)
314 walk_expression(stmt->fors.step, env);
315 walk_statement(stmt->fors.body, env);
319 walk_expression(stmt->ifs.condition, env);
320 walk_statement(stmt->ifs.true_statement, env);
321 if (stmt->ifs.false_statement != NULL)
322 walk_statement(stmt->ifs.false_statement, env);
325 case STATEMENT_SWITCH:
326 walk_expression(stmt->switchs.expression, env);
327 walk_statement(stmt->switchs.body, env);
330 case STATEMENT_LABEL:
331 walk_statement(stmt->label.statement, env);
334 case STATEMENT_CASE_LABEL:
335 walk_statement(stmt->case_label.statement, env);
338 case STATEMENT_WHILE:
339 walk_expression(stmt->whiles.condition, env);
340 walk_statement(stmt->whiles.body, env);
343 case STATEMENT_DO_WHILE:
344 walk_statement(stmt->do_while.body, env);
345 walk_expression(stmt->do_while.condition, env);
348 case STATEMENT_EXPRESSION:
349 walk_expression(stmt->expression.expression, env);
352 case STATEMENT_RETURN:
353 if (stmt->returns.value != NULL)
354 walk_expression(stmt->returns.value, env);
357 case STATEMENT_DECLARATION:
358 walk_declarations(stmt->declaration.declarations_begin,
359 stmt->declaration.declarations_end, env);
362 case STATEMENT_MS_TRY:
363 walk_statement(stmt->ms_try.try_statement, env);
364 walk_statement(stmt->ms_try.final_statement, env);
367 case STATEMENT_INVALID:
368 case STATEMENT_EMPTY:
369 case STATEMENT_CONTINUE:
370 case STATEMENT_BREAK:
373 case STATEMENT_LEAVE:
377 panic("unhandled statement");
380 static void null_declaration_func(entity_t *entity, void *env)
386 static void null_statement_func(statement_t *statement, void *env)
392 static void null_expression_func(expression_t *expression, void *env)
398 void walk_translation_unit(translation_unit_t *unit,
399 declaration_callback declaration_func,
400 statement_callback statement_func,
401 expression_callback expression_func, void *env)
403 walk_env_t walk_env = {
404 pset_new_ptr_default(),
405 declaration_func != NULL ? declaration_func : null_declaration_func,
406 statement_func != NULL ? statement_func : null_statement_func,
407 expression_func != NULL ? expression_func : null_expression_func,
410 walk_scope(&unit->scope, &walk_env);
411 del_pset(walk_env.visited_types);
414 void walk_statements(statement_t *statement, statement_callback func, void *env)
417 = { pset_new_ptr_default(),
418 null_declaration_func, func, null_expression_func, env };
419 walk_statement(statement, &walk_env);
420 del_pset(walk_env.visited_types);