diff options
author | Søren Sandmann <sandmann@redhat.com> | 2007-07-24 13:12:52 -0400 |
---|---|---|
committer | Søren Sandmann <sandmann@redhat.com> | 2007-07-24 13:12:52 -0400 |
commit | 165395185f6abf63d7c703d5eae857ed2934667b (patch) | |
tree | 9e35f18b05da9880e1f2c0ffd047d79dd2a99940 /return-check.c | |
parent | 11fa9b586f191e61db2919a0618157687230ddaf (diff) |
Much simpler graph based return check
Diffstat (limited to 'return-check.c')
-rw-r--r-- | return-check.c | 127 |
1 files changed, 21 insertions, 106 deletions
diff --git a/return-check.c b/return-check.c index 197baf7..58aa86a 100644 --- a/return-check.c +++ b/return-check.c @@ -18,114 +18,17 @@ #include "ast.h" -static gboolean return_check_statement (ast_statement_t *statement, - gboolean *returns); - static gboolean -return_check_function (ast_function_definition_t *function) +check_graph (node_t *exit) { - gboolean returns; - - if (!return_check_statement (function->body, &returns)) - return FALSE; + int i; - if (!returns && function->return_type->common.type != AST_VOID_TYPE) + for (i = 0; i < exit->predecessors->len; ++i) { - g_print ("Control reaches end of non void function %s\n", function->name); - return FALSE; - } - - return TRUE; -} + node_t *pred = exit->predecessors->pdata[i]; -static gboolean -return_check_definition (ast_definition_t *definition) -{ - switch (definition->common.type) - { - case AST_FUNCTION_DEFINITION: - if (!return_check_function (&definition->function)) + if (pred->reachable && !pred->return_) return FALSE; - break; - - case AST_VARIABLE_DEFINITION: - break; - } - - return TRUE; -} - -static gboolean -return_check_statement (ast_statement_t *statement, - gboolean *returns) -{ - gboolean b1, b2; - - *returns = FALSE; - - switch (statement->common.type) - { - case AST_DEFINITION_STATEMENT: - if (!return_check_definition (statement->definition.def)) - return FALSE; - break; - - case AST_WHILE_STATEMENT: - if (!return_check_statement (statement->while_.body, &b1)) - return FALSE; - break; - - case AST_FOR_STATEMENT: - if (!return_check_statement (statement->for_.body, &b1)) - return FALSE; - break; - - case AST_IF_STATEMENT: - if (!return_check_statement (statement->if_.then_part, &b1)) - return FALSE; - - if (!return_check_statement (statement->if_.else_part, &b2)) - return FALSE; - - *returns = b1 && b2; - break; - - case AST_COMPOUND_STATEMENT: - if (!return_check_statement (statement->compound.first, &b1)) - return FALSE; - - if (!return_check_statement (statement->compound.second, &b2)) - return FALSE; - - *returns = b1 || b2; - break; - - case AST_BLOCK_STATEMENT: - if (!return_check_statement (statement->block.body, returns)) - return FALSE; - break; - - case AST_GOTO_STATEMENT: - /* FIXME: gotos have completely broken this pass - * We should probably make it graph based. - */ - break; - - case AST_LABEL_STATEMENT: - break; - - case AST_PRINT_STATEMENT: - break; - - case AST_EXPRESSION_STATEMENT: - break; - - case AST_RETURN_STATEMENT: - *returns = TRUE; - break; - - case AST_EMPTY_STATEMENT: - break; } return TRUE; @@ -134,10 +37,22 @@ return_check_statement (ast_statement_t *statement, gboolean return_check (ast_program_t *program) { - gboolean dummy; - - if (!return_check_statement (program->statement, &dummy)) - return FALSE; + int i; + + for (i = 0; program->functions[i] != NULL; ++i) + { + ast_function_definition_t *function = program->functions[i]; + + if (function->return_type->common.type != AST_VOID_TYPE) + { + if (function->exit && !check_graph (function->exit)) + { + g_print ("Control reaches end of non-void function %s\n", + function->name); + return FALSE; + } + } + } return TRUE; } |