diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2018-09-23 11:52:46 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2018-09-23 11:52:46 +0200 |
commit | 92237eae4d9fdd39b485394beac5713b635d25bb (patch) | |
tree | 6be7375ea025390ed92e90427716b989104514ac | |
parent | b528f00ebd7c878b4afcffd93c001f0f178206bb (diff) | |
download | cython-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.py | 16 | ||||
-rw-r--r-- | tests/run/switch.pyx | 1 | ||||
-rw-r--r-- | tests/run/switch_transform.pyx | 1 |
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: |