mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 22:31:05 +00:00
Ensure functions are always properly terminated.
Control that reaches the end of a function must see a return statement.
This commit is contained in:
parent
9159daf99d
commit
80424f6ad5
2 changed files with 37 additions and 1 deletions
|
@ -617,7 +617,7 @@ emit_function (function_t *f, expr_t *e)
|
|||
//statement_t *s;
|
||||
|
||||
f->code = pr.code->size;
|
||||
printf ("%s %d\n", f->name, f->code);
|
||||
//printf ("%s %d\n", f->name, f->code);
|
||||
sblock = make_statements (e);
|
||||
//for (/**/; sblock; sblock = sblock->next) {
|
||||
// printf ("block %p\n", sblock);
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "diagnostic.h"
|
||||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "options.h"
|
||||
#include "qc-parse.h"
|
||||
#include "qfcc.h"
|
||||
|
@ -843,6 +844,40 @@ remove_dead_blocks (sblock_t *blocks)
|
|||
} while (did_something);
|
||||
}
|
||||
|
||||
static void
|
||||
check_final_block (sblock_t *sblock)
|
||||
{
|
||||
statement_t *s;
|
||||
symbol_t *return_symbol = 0;
|
||||
operand_t *return_operand = 0;
|
||||
const char *return_opcode = "<RETURN_V>";
|
||||
|
||||
if (!sblock)
|
||||
return;
|
||||
while (sblock->next)
|
||||
sblock = sblock->next;
|
||||
s = (statement_t *) sblock->tail;
|
||||
if (!strcmp (s->opcode, "<GOTO>"))
|
||||
return; // the end of function is the end of a loop
|
||||
if (!strncmp (s->opcode, "<RETURN", 7))
|
||||
return;
|
||||
if (current_func->sym->type->t.func.type != &type_void)
|
||||
warning (0, "control reaches end of non-void function");
|
||||
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
||||
expr_t *e = new_ret_expr (current_func->sym->type->t.func.type);
|
||||
return_symbol = e->e.expr.e1->e.expr.e1->e.symbol;//FIXME ick
|
||||
return_opcode = "<RETURN>";
|
||||
}
|
||||
if (return_symbol) {
|
||||
return_operand = new_operand (op_symbol);
|
||||
return_operand->type = ev_void;
|
||||
return_operand->o.symbol = return_symbol;
|
||||
}
|
||||
s = new_statement (return_opcode);
|
||||
s->opa = return_operand;
|
||||
sblock_add_statement (sblock, s);
|
||||
}
|
||||
|
||||
sblock_t *
|
||||
make_statements (expr_t *e)
|
||||
{
|
||||
|
@ -851,6 +886,7 @@ make_statements (expr_t *e)
|
|||
statement_slist (sblock, e);
|
||||
// print_flow (sblock);
|
||||
remove_dead_blocks (sblock);
|
||||
check_final_block (sblock);
|
||||
// print_flow (sblock);
|
||||
return sblock;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue