mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +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;
|
//statement_t *s;
|
||||||
|
|
||||||
f->code = pr.code->size;
|
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);
|
sblock = make_statements (e);
|
||||||
//for (/**/; sblock; sblock = sblock->next) {
|
//for (/**/; sblock; sblock = sblock->next) {
|
||||||
// printf ("block %p\n", sblock);
|
// printf ("block %p\n", sblock);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
|
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
#include "function.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "qc-parse.h"
|
#include "qc-parse.h"
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
|
@ -843,6 +844,40 @@ remove_dead_blocks (sblock_t *blocks)
|
||||||
} while (did_something);
|
} 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 *
|
sblock_t *
|
||||||
make_statements (expr_t *e)
|
make_statements (expr_t *e)
|
||||||
{
|
{
|
||||||
|
@ -851,6 +886,7 @@ make_statements (expr_t *e)
|
||||||
statement_slist (sblock, e);
|
statement_slist (sblock, e);
|
||||||
// print_flow (sblock);
|
// print_flow (sblock);
|
||||||
remove_dead_blocks (sblock);
|
remove_dead_blocks (sblock);
|
||||||
|
check_final_block (sblock);
|
||||||
// print_flow (sblock);
|
// print_flow (sblock);
|
||||||
return sblock;
|
return sblock;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue