summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2018-09-23 11:52:46 +0200
committerStefan Behnel <stefan_ml@behnel.de>2018-09-23 11:52:46 +0200
commit92237eae4d9fdd39b485394beac5713b635d25bb (patch)
tree6be7375ea025390ed92e90427716b989104514ac
parentb528f00ebd7c878b4afcffd93c001f0f178206bb (diff)
downloadcython-92237eae4d9fdd39b485394beac5713b635d25bb.tar.gz
Make switch-statement work nicely with line tracing.
Previously, line tracing code could be generated before the case-statements and thus be ignored at best or rejected by the C compiler.
-rw-r--r--Cython/Compiler/Nodes.py16
-rw-r--r--tests/run/switch.pyx1
-rw-r--r--tests/run/switch_transform.pyx1
3 files changed, 16 insertions, 2 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index e06bfdc9b..0d72024a9 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -6330,11 +6330,19 @@ class SwitchCaseNode(StatNode):
child_attrs = ['conditions', 'body']
- def generate_execution_code(self, code):
+ def generate_condition_evaluation_code(self, code):
for cond in self.conditions:
- code.mark_pos(cond.pos)
cond.generate_evaluation_code(code)
+
+ def generate_execution_code(self, code):
+ num_conditions = len(self.conditions)
+ line_tracing_enabled = code.globalstate.directives['linetrace']
+ for i, cond in enumerate(self.conditions):
code.putln("case %s:" % cond.result())
+ code.mark_pos(cond.pos) # Tracing code must appear *after* the 'case' statement.
+ if line_tracing_enabled and i + 1 < num_conditions:
+ # Allow fall-through after the line tracing code.
+ code.putln('CYTHON_FALLTHROUGH;')
self.body.generate_execution_code(code)
code.mark_pos(self.pos, trace=False)
code.putln("break;")
@@ -6361,6 +6369,10 @@ class SwitchStatNode(StatNode):
def generate_execution_code(self, code):
self.test.generate_evaluation_code(code)
+ # Make sure all conditions are evaluated before going into the switch() statement.
+ # This is required in order to prevent any execution code from leaking into the space between the cases.
+ for case in self.cases:
+ case.generate_condition_evaluation_code(code)
code.mark_pos(self.pos)
code.putln("switch (%s) {" % self.test.result())
for case in self.cases:
diff --git a/tests/run/switch.pyx b/tests/run/switch.pyx
index eb0b8145a..dfd734fce 100644
--- a/tests/run/switch.pyx
+++ b/tests/run/switch.pyx
@@ -1,4 +1,5 @@
# mode: run
+# cython: linetrace=True
cimport cython
diff --git a/tests/run/switch_transform.pyx b/tests/run/switch_transform.pyx
index eccf70814..0c63c4213 100644
--- a/tests/run/switch_transform.pyx
+++ b/tests/run/switch_transform.pyx
@@ -1,4 +1,5 @@
# cython: optimize.use_switch=False
+# cython: linetrace=True
cdef extern from *:
enum: