Commit 760bdc3c authored by scoder's avatar scoder

Merge pull request #29 from vitek/unreachable_code

Unreachable code removal
parents a6ec5007 82357f1c
......@@ -109,6 +109,7 @@ class Context(object):
from ParseTreeTransforms import ExpandInplaceOperators, ParallelRangeTransform
from TypeInference import MarkAssignments, MarkOverflowingArithmetic
from ParseTreeTransforms import AlignFunctionDefinitions, GilCheck
from ParseTreeTransforms import RemoveUnreachableCode
from AnalysedTreeTransforms import AutoTestDictTransform
from AutoDocTransforms import EmbedSignature
from Optimize import FlattenInListTransform, SwitchTransform, IterationTransform
......@@ -138,6 +139,7 @@ class Context(object):
ParallelRangeTransform(self),
MarkClosureVisitor(self),
_align_function_definitions,
RemoveUnreachableCode(self),
ConstantFolding(),
FlattenInListTransform(),
WithTransform(self),
......
......@@ -128,6 +128,7 @@ class Node(object):
is_name = 0
is_literal = 0
is_terminator = 0
temps = None
# All descandants should set child_attrs to a list of the attributes
......@@ -4049,6 +4050,7 @@ class PassStatNode(StatNode):
class BreakStatNode(StatNode):
child_attrs = []
is_terminator = True
def analyse_expressions(self, env):
pass
......@@ -4063,6 +4065,7 @@ class BreakStatNode(StatNode):
class ContinueStatNode(StatNode):
child_attrs = []
is_terminator = True
def analyse_expressions(self, env):
pass
......@@ -4083,6 +4086,7 @@ class ReturnStatNode(StatNode):
# return_type PyrexType
child_attrs = ["value"]
is_terminator = True
def analyse_expressions(self, env):
return_type = env.return_type
......@@ -4156,6 +4160,7 @@ class RaiseStatNode(StatNode):
# cause ExprNode or None
child_attrs = ["exc_type", "exc_value", "exc_tb", "cause"]
is_terminator = True
def analyse_expressions(self, env):
if self.exc_type:
......@@ -4250,6 +4255,7 @@ class RaiseStatNode(StatNode):
class ReraiseStatNode(StatNode):
child_attrs = []
is_terminator = True
def analyse_expressions(self, env):
env.use_utility_code(restore_exception_utility_code)
......
......@@ -94,6 +94,10 @@ directive_defaults = {
'warn': None,
'warn.undeclared': False,
'warn.unreachable': True,
# remove unreachable code
'remove_unreachable': True,
# test support
'test_assert_path_exists' : [],
......
......@@ -1666,6 +1666,43 @@ class AlignFunctionDefinitions(CythonTransform):
return node
class RemoveUnreachableCode(CythonTransform):
def visit_Node(self, node):
self.visitchildren(node)
return node
def visit_StatListNode(self, node):
if not self.current_directives['remove_unreachable']:
return node
self.visitchildren(node)
for idx, stat in enumerate(node.stats):
idx += 1
if stat.is_terminator:
if idx < len(node.stats):
if self.current_directives['warn.unreachable']:
warning(node.stats[idx].pos, "Unreachable code", 2)
node.stats = node.stats[:idx]
node.is_terminator = True
break
return node
def visit_IfClauseNode(self, node):
self.visitchildren(node)
if node.body.is_terminator:
node.is_terminator = True
return node
def visit_IfStatNode(self, node):
self.visitchildren(node)
if node.else_clause and node.else_clause.is_terminator:
for clause in node.if_clauses:
if not clause.is_terminator:
break
else:
node.is_terminator = True
return node
class YieldNodeCollector(TreeVisitor):
def __init__(self):
......
# cython: remove_unreachable=False
# mode: error
break
......@@ -27,11 +28,11 @@ def bool_result():
_ERRORS = u'''
3:0: break statement not inside loop
6:4: break statement not inside loop
9:4: break statement not inside loop
12:4: break statement not inside loop
17:5: break statement not inside loop
21:4: break statement not inside loop
23:4: break statement not inside loop
4:0: break statement not inside loop
7:4: break statement not inside loop
10:4: break statement not inside loop
13:4: break statement not inside loop
18:5: break statement not inside loop
22:4: break statement not inside loop
24:4: break statement not inside loop
'''
# cython: remove_unreachable=False
# mode: error
continue
......@@ -26,11 +27,11 @@ def bool_result():
return True
_ERRORS = u'''
3:0: continue statement not inside loop
6:4: continue statement not inside loop
9:4: continue statement not inside loop
12:4: continue statement not inside loop
17:5: continue statement not inside loop
21:4: continue statement not inside loop
23:4: continue statement not inside loop
4:0: continue statement not inside loop
7:4: continue statement not inside loop
10:4: continue statement not inside loop
13:4: continue statement not inside loop
18:5: continue statement not inside loop
22:4: continue statement not inside loop
24:4: continue statement not inside loop
'''
# cython: remove_unreachable=False
# mode: error
cdef void g():
......@@ -9,7 +10,7 @@ cdef int h():
return # error
return p # error
_ERRORS = u"""
5:17: Return with value in void function
9:1: Return value required
10:17: Cannot assign type 'int *' to 'int'
6:17: Return with value in void function
10:1: Return value required
11:17: Cannot assign type 'int *' to 'int'
"""
# cython: remove_unreachable=False
# mode: error
def f(a, b):
......@@ -5,6 +6,6 @@ def f(a, b):
break # error
continue # error
_ERRORS = u"""
5:1: break statement not inside loop
6:1: continue statement not inside loop
6:1: break statement not inside loop
7:1: continue statement not inside loop
"""
# cython: remove_unreachable=False
# mode: error
cdef object f(object x) nogil:
......@@ -92,71 +93,71 @@ def bare_pyvar_name(object x):
# except these: 29, 34, 44, 56, 58, 60, 62-64
_ERRORS = u"""
3:5: Function with Python return type cannot be declared nogil
6:5: Function declared nogil has Python locals or temporaries
8:6: Assignment of Python object not allowed without gil
11:5: Discarding owned Python object not allowed without gil
13:5: Function with Python return type cannot be declared nogil
17:5: Calling gil-requiring function not allowed without gil
26:9: Calling gil-requiring function not allowed without gil
28:12: Assignment of Python object not allowed without gil
30:8: Discarding owned Python object not allowed without gil
30:16: Constructing complex number not allowed without gil
32:8: Backquote expression not allowed without gil
32:8: Discarding owned Python object not allowed without gil
32:9: Operation not allowed without gil
33:15: Assignment of Python object not allowed without gil
33:15: Operation not allowed without gil
33:15: Python import not allowed without gil
34:8: Operation not allowed without gil
34:13: Python import not allowed without gil
34:25: Constructing Python list not allowed without gil
34:25: Operation not allowed without gil
35:17: Iterating over Python object not allowed without gil
37:11: Discarding owned Python object not allowed without gil
37:11: Indexing Python object not allowed without gil
4:5: Function with Python return type cannot be declared nogil
7:5: Function declared nogil has Python locals or temporaries
9:6: Assignment of Python object not allowed without gil
12:5: Discarding owned Python object not allowed without gil
14:5: Function with Python return type cannot be declared nogil
18:5: Calling gil-requiring function not allowed without gil
27:9: Calling gil-requiring function not allowed without gil
29:12: Assignment of Python object not allowed without gil
31:8: Discarding owned Python object not allowed without gil
31:16: Constructing complex number not allowed without gil
33:8: Backquote expression not allowed without gil
33:8: Discarding owned Python object not allowed without gil
33:9: Operation not allowed without gil
34:15: Assignment of Python object not allowed without gil
34:15: Operation not allowed without gil
34:15: Python import not allowed without gil
35:8: Operation not allowed without gil
35:13: Python import not allowed without gil
35:25: Constructing Python list not allowed without gil
35:25: Operation not allowed without gil
36:17: Iterating over Python object not allowed without gil
38:11: Discarding owned Python object not allowed without gil
38:11: Slicing Python object not allowed without gil
39:11: Constructing Python slice object not allowed without gil
38:11: Indexing Python object not allowed without gil
39:11: Discarding owned Python object not allowed without gil
39:11: Indexing Python object not allowed without gil
39:13: Converting to Python object not allowed without gil
39:15: Converting to Python object not allowed without gil
39:17: Converting to Python object not allowed without gil
40:11: Accessing Python attribute not allowed without gil
39:11: Slicing Python object not allowed without gil
40:11: Constructing Python slice object not allowed without gil
40:11: Discarding owned Python object not allowed without gil
41:9: Constructing Python tuple not allowed without gil
41:9: Discarding owned Python object not allowed without gil
42:8: Constructing Python list not allowed without gil
42:8: Discarding owned Python object not allowed without gil
43:8: Constructing Python dict not allowed without gil
40:11: Indexing Python object not allowed without gil
40:13: Converting to Python object not allowed without gil
40:15: Converting to Python object not allowed without gil
40:17: Converting to Python object not allowed without gil
41:11: Accessing Python attribute not allowed without gil
41:11: Discarding owned Python object not allowed without gil
42:9: Constructing Python tuple not allowed without gil
42:9: Discarding owned Python object not allowed without gil
43:8: Constructing Python list not allowed without gil
43:8: Discarding owned Python object not allowed without gil
44:12: Discarding owned Python object not allowed without gil
44:12: Truth-testing Python object not allowed without gil
45:13: Python type test not allowed without gil
47:10: Discarding owned Python object not allowed without gil
47:10: Operation not allowed without gil
48:8: Discarding owned Python object not allowed without gil
48:8: Operation not allowed without gil
49:10: Assignment of Python object not allowed without gil
49:14: Assignment of Python object not allowed without gil
50:9: Assignment of Python object not allowed without gil
50:13: Assignment of Python object not allowed without gil
50:16: Creating temporary Python reference not allowed without gil
50:19: Creating temporary Python reference not allowed without gil
51:11: Assignment of Python object not allowed without gil
51:11: Indexing Python object not allowed without gil
52:11: Accessing Python attribute not allowed without gil
44:8: Constructing Python dict not allowed without gil
44:8: Discarding owned Python object not allowed without gil
45:12: Discarding owned Python object not allowed without gil
45:12: Truth-testing Python object not allowed without gil
46:13: Python type test not allowed without gil
48:10: Discarding owned Python object not allowed without gil
48:10: Operation not allowed without gil
49:8: Discarding owned Python object not allowed without gil
49:8: Operation not allowed without gil
50:10: Assignment of Python object not allowed without gil
50:14: Assignment of Python object not allowed without gil
51:9: Assignment of Python object not allowed without gil
51:13: Assignment of Python object not allowed without gil
51:16: Creating temporary Python reference not allowed without gil
51:19: Creating temporary Python reference not allowed without gil
52:11: Assignment of Python object not allowed without gil
53:8: Constructing Python tuple not allowed without gil
53:8: Python print statement not allowed without gil
54:8: Deleting Python object not allowed without gil
55:8: Returning Python object not allowed without gil
56:8: Raising exception not allowed without gil
57:14: Truth-testing Python object not allowed without gil
59:17: Truth-testing Python object not allowed without gil
61:8: For-loop using object bounds or target not allowed without gil
63:8: Try-except statement not allowed without gil
67:8: Try-finally statement not allowed without gil
84:8: For-loop using object bounds or target not allowed without gil
52:11: Indexing Python object not allowed without gil
53:11: Accessing Python attribute not allowed without gil
53:11: Assignment of Python object not allowed without gil
54:8: Constructing Python tuple not allowed without gil
54:8: Python print statement not allowed without gil
55:8: Deleting Python object not allowed without gil
56:8: Returning Python object not allowed without gil
57:8: Raising exception not allowed without gil
58:14: Truth-testing Python object not allowed without gil
60:17: Truth-testing Python object not allowed without gil
62:8: For-loop using object bounds or target not allowed without gil
64:8: Try-except statement not allowed without gil
68:8: Try-finally statement not allowed without gil
85:8: For-loop using object bounds or target not allowed without gil
"""
# cython: remove_unreachable=False
# ticket: 135
# mode: error
......@@ -31,13 +32,13 @@ else:
_ERRORS = u'''
7:0: Return not inside a function body
10:4: Return not inside a function body
13:4: Return not inside a function body
15:5: Return not inside a function body
18:5: Return not inside a function body
22:4: Return not inside a function body
25:4: Return not inside a function body
28:4: Return not inside a function body
30:4: Return not inside a function body
8:0: Return not inside a function body
11:4: Return not inside a function body
14:4: Return not inside a function body
16:5: Return not inside a function body
19:5: Return not inside a function body
23:4: Return not inside a function body
26:4: Return not inside a function body
29:4: Return not inside a function body
31:4: Return not inside a function body
'''
# mode: error
# tag: werror
def simple_return():
return
print 'Where am I?'
def simple_loops(*args):
for i in args:
continue
print 'Never be here'
while True:
break
print 'Never be here'
def conditional(a, b):
if a:
return 1
elif b:
return 2
else:
return 3
print 'oops'
_ERRORS = """
6:4: Unreachable code
11:8: Unreachable code
15:8: Unreachable code
24:4: Unreachable code
"""
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment