summaryrefslogtreecommitdiff
path: root/Cython/Compiler/ParseTreeTransforms.py
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2018-09-19 22:31:19 +0200
committerStefan Behnel <stefan_ml@behnel.de>2018-09-19 22:31:19 +0200
commit7b4079c50d88f5ce1cf3cc55a6f46cd6e35cbda4 (patch)
tree342f4335ea8ba71cfa358778ca14a63d552fa4b3 /Cython/Compiler/ParseTreeTransforms.py
parent04114b9b927c22b7cf0510f7b1587b691acb14bc (diff)
downloadcython-7b4079c50d88f5ce1cf3cc55a6f46cd6e35cbda4.tar.gz
Check some child nodes against the correct nogil context when they are actually being evaluated in the outer scope (e.g default arguments or annotations of a nogil function).
Diffstat (limited to 'Cython/Compiler/ParseTreeTransforms.py')
-rw-r--r--Cython/Compiler/ParseTreeTransforms.py36
1 files changed, 24 insertions, 12 deletions
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py
index 6d56e5aac..154f341ae 100644
--- a/Cython/Compiler/ParseTreeTransforms.py
+++ b/Cython/Compiler/ParseTreeTransforms.py
@@ -2861,24 +2861,33 @@ class GilCheck(VisitorTransform):
self.nogil_declarator_only = False
return super(GilCheck, self).__call__(root)
+ def _visit_scoped_children(self, node, gil_state):
+ was_nogil = self.nogil
+ outer_attrs = node.outer_attrs
+ if outer_attrs and len(self.env_stack) > 1:
+ self.nogil = self.env_stack[-2].nogil
+ self.visitchildren(node, outer_attrs)
+
+ self.nogil = gil_state
+ self.visitchildren(node, exclude=outer_attrs)
+ self.nogil = was_nogil
+
def visit_FuncDefNode(self, node):
self.env_stack.append(node.local_scope)
- was_nogil = self.nogil
- self.nogil = node.local_scope.nogil
+ inner_nogil = node.local_scope.nogil
- if self.nogil:
+ if inner_nogil:
self.nogil_declarator_only = True
- if self.nogil and node.nogil_check:
+ if inner_nogil and node.nogil_check:
node.nogil_check(node.local_scope)
- self.visitchildren(node)
+ self._visit_scoped_children(node, inner_nogil)
# This cannot be nested, so it doesn't need backup/restore
self.nogil_declarator_only = False
self.env_stack.pop()
- self.nogil = was_nogil
return node
def visit_GILStatNode(self, node):
@@ -2886,9 +2895,9 @@ class GilCheck(VisitorTransform):
node.nogil_check()
was_nogil = self.nogil
- self.nogil = (node.state == 'nogil')
+ is_nogil = (node.state == 'nogil')
- if was_nogil == self.nogil and not self.nogil_declarator_only:
+ if was_nogil == is_nogil and not self.nogil_declarator_only:
if not was_nogil:
error(node.pos, "Trying to acquire the GIL while it is "
"already held.")
@@ -2901,8 +2910,7 @@ class GilCheck(VisitorTransform):
# which is wrapped in a StatListNode. Just unpack that.
node.finally_clause, = node.finally_clause.stats
- self.visitchildren(node)
- self.nogil = was_nogil
+ self._visit_scoped_children(node, is_nogil)
return node
def visit_ParallelRangeNode(self, node):
@@ -2949,8 +2957,12 @@ class GilCheck(VisitorTransform):
def visit_Node(self, node):
if self.env_stack and self.nogil and node.nogil_check:
node.nogil_check(self.env_stack[-1])
- self.visitchildren(node)
- node.in_nogil_context = self.nogil
+ if node.outer_attrs:
+ self._visit_scoped_children(node, self.nogil)
+ else:
+ self.visitchildren(node)
+ if self.nogil:
+ node.in_nogil_context = True
return node