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