summaryrefslogtreecommitdiff
path: root/return-check.c
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2007-07-24 13:12:52 -0400
committerSøren Sandmann <sandmann@redhat.com>2007-07-24 13:12:52 -0400
commit165395185f6abf63d7c703d5eae857ed2934667b (patch)
tree9e35f18b05da9880e1f2c0ffd047d79dd2a99940 /return-check.c
parent11fa9b586f191e61db2919a0618157687230ddaf (diff)
Much simpler graph based return check
Diffstat (limited to 'return-check.c')
-rw-r--r--return-check.c127
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;
}