mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
Append a new sblock for return when necessary.
If the final block ends in a conditional statement, appending return to the block will hide the conditional statement from the flow analyzer. This may cause the conditional statement's destination node be become unreachable according to the analyzer and thus eliminated. The label for the branch then loses its target sblock and thus the code generator will produce a zero-distance jump resulting in an infinite loop. Thus, if the final block ends in a conditional statement (or, for completeness, a call statement), append a new empty block before adding the return statement.
This commit is contained in:
parent
cb39cfc9ae
commit
7701393bd4
3 changed files with 33 additions and 2 deletions
|
@ -1512,7 +1512,7 @@ remove_dead_blocks (sblock_t *blocks)
|
||||||
static void
|
static void
|
||||||
check_final_block (sblock_t *sblock)
|
check_final_block (sblock_t *sblock)
|
||||||
{
|
{
|
||||||
statement_t *s;
|
statement_t *s = 0;
|
||||||
symbol_t *return_symbol = 0;
|
symbol_t *return_symbol = 0;
|
||||||
def_t *return_def = 0;
|
def_t *return_def = 0;
|
||||||
operand_t *return_operand = 0;
|
operand_t *return_operand = 0;
|
||||||
|
@ -1531,6 +1531,12 @@ check_final_block (sblock_t *sblock)
|
||||||
}
|
}
|
||||||
if (current_func->sym->type->t.func.type != &type_void)
|
if (current_func->sym->type->t.func.type != &type_void)
|
||||||
warning (0, "control reaches end of non-void function");
|
warning (0, "control reaches end of non-void function");
|
||||||
|
if (s && s->type >= st_func) {
|
||||||
|
// func and flow end blocks, so we need to add a new block to take the
|
||||||
|
// return
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
sblock = sblock->next;
|
||||||
|
}
|
||||||
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
||||||
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
|
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
|
||||||
sc_extern);
|
sc_extern);
|
||||||
|
|
|
@ -29,7 +29,8 @@ test_progs_dat=\
|
||||||
structlive.dat \
|
structlive.dat \
|
||||||
structptr.dat \
|
structptr.dat \
|
||||||
vecinit.dat \
|
vecinit.dat \
|
||||||
while.dat
|
while.dat \
|
||||||
|
voidfor.dat
|
||||||
|
|
||||||
fail_progs_dat=\
|
fail_progs_dat=\
|
||||||
$E
|
$E
|
||||||
|
@ -120,6 +121,13 @@ while.dat: $(while_obj) $(QFCC_DEP)
|
||||||
while.run: Makefile build-run
|
while.run: Makefile build-run
|
||||||
$(srcdir)/build-run $@
|
$(srcdir)/build-run $@
|
||||||
|
|
||||||
|
voidfor_dat_SOURCES=voidfor.r
|
||||||
|
voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo)
|
||||||
|
voidfor.dat: $(voidfor_obj) $(QFCC_DEP)
|
||||||
|
$(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj)
|
||||||
|
voidfor.run: Makefile build-run
|
||||||
|
$(srcdir)/build-run $@
|
||||||
|
|
||||||
include ./$(DEPDIR)/*.Qo
|
include ./$(DEPDIR)/*.Qo
|
||||||
|
|
||||||
EXTRA_DIST= test-bi.h build-run
|
EXTRA_DIST= test-bi.h build-run
|
||||||
|
|
17
tools/qfcc/test/voidfor.r
Normal file
17
tools/qfcc/test/voidfor.r
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
void bar ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 11; i++)
|
||||||
|
bar ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
foo ();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue