Fix two issues in the dead code removal module

1. When the last statement of a function is a RETURN statement which is syntactically required, it could still be deleted.
2. The child of a RETURN statement could be removed if the statement was not executed.

This commit fixes both issues.

Bug report and test case provided by @Tonaie. Fixes #14.
This commit is contained in:
Sei Lisa 2020-06-01 20:49:48 +02:00
parent 0affbf13dd
commit d6bf0c390e
2 changed files with 22 additions and 10 deletions

View file

@ -386,7 +386,7 @@ class deadcode(object):
return False
def CleanNode(self, curnode):
def CleanNode(self, curnode, isFnDef = False):
"""Recursively checks if the children are used, deleting those that are
not.
"""
@ -402,13 +402,24 @@ class deadcode(object):
node = curnode.ch[index]
if not hasattr(node, 'X'):
if curnode.ch[index].nt == 'JUMP':
deleted = curnode.ch[index]
# Don't delete the child of a RETURN statement!
if curnode.nt == 'RETURN':
pass
# If it's a RETURN as the last statement of a block in a
# function definition, don't delete it (a hacky workaround for
# issue #14).
elif (deleted.nt == 'RETURN' and index == len(curnode.ch) - 1
and isFnDef):
pass
else:
del curnode.ch[index]
if deleted.nt == 'JUMP':
# Decrease label reference count
scope = curnode.ch[index].scope
name = curnode.ch[index].name
scope = deleted.scope
name = deleted.name
assert self.symtab[scope][name]['ref'] > 0
self.symtab[scope][name]['ref'] -= 1
del curnode.ch[index]
continue
nt = node.nt
@ -484,7 +495,7 @@ class deadcode(object):
child[1] = nr(nt='CONST', X=True, SEF=True, t='integer',
value=0)
self.CleanNode(node)
self.CleanNode(node, isFnDef = (curnode.nt == 'FNDEF'))
index += 1

View file

@ -0,0 +1 @@
Skipped because our fix to #14 brings back the RETURN statement.