summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2020-05-17 18:31:12 +0100
committerGitHub <noreply@github.com>2020-05-17 19:31:12 +0200
commit6313c86737f8f8a795e356ae6da0bc59fb68b159 (patch)
treec1c974c0b4615a42d35fdb6137febb6ae51c09a3
parent83ac1a27735d562baf58f3577bc933ee7cbb8c29 (diff)
downloadcython-6313c86737f8f8a795e356ae6da0bc59fb68b159.tar.gz
Ensure utility code keeps the directives that it was compiled with (GH-3615)
When it's merged into the main module, wrap it in a CompilerDirectivesNode.
-rw-r--r--Cython/Compiler/ModuleNode.py8
-rw-r--r--Cython/Compiler/Pipeline.py3
-rw-r--r--tests/memoryview/memoryview_no_binding_T3613.pyx21
3 files changed, 30 insertions, 2 deletions
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index ea003bf31..4023a1dde 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -87,7 +87,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
child_attrs = ["body"]
directives = None
-
def merge_in(self, tree, scope, merge_scope=False):
# Merges in the contents of another tree, and possibly scope. With the
# current implementation below, this must be done right prior
@@ -123,6 +122,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.scope.merge_in(scope)
+ def with_compiler_directives(self):
+ # When merging a utility code module into the user code we need to preserve
+ # the original compiler directives. This returns the body of the module node,
+ # wrapped in its set of directives.
+ body = Nodes.CompilerDirectivesNode(self.pos, directives=self.directives, body=self.body)
+ return body
+
def analyse_declarations(self, env):
if has_np_pythran(env):
Pythran.include_pythran_generic(env)
diff --git a/Cython/Compiler/Pipeline.py b/Cython/Compiler/Pipeline.py
index 5194c3e49..5bab4dbdb 100644
--- a/Cython/Compiler/Pipeline.py
+++ b/Cython/Compiler/Pipeline.py
@@ -128,7 +128,8 @@ def inject_utility_code_stage_factory(context):
module_node.scope.utility_code_list.append(dep)
tree = utilcode.get_tree(cython_scope=context.cython_scope)
if tree:
- module_node.merge_in(tree.body, tree.scope, merge_scope=True)
+ module_node.merge_in(tree.with_compiler_directives(),
+ tree.scope, merge_scope=True)
return module_node
return inject_utility_code_stage
diff --git a/tests/memoryview/memoryview_no_binding_T3613.pyx b/tests/memoryview/memoryview_no_binding_T3613.pyx
new file mode 100644
index 000000000..1c736359e
--- /dev/null
+++ b/tests/memoryview/memoryview_no_binding_T3613.pyx
@@ -0,0 +1,21 @@
+# mode: compile
+# tag: memoryview
+
+# cython: binding=False
+
+# See GH 3613 - when memoryviews were compiled with binding off they ended up in an
+# inconsistent state where different directives were applied at different stages
+# of the pipeline
+
+import cython
+
+def f(double[:] a):
+ pass
+
+@cython.binding(False)
+def g(double[:] a):
+ pass
+
+@cython.binding(True)
+def h(double[:] a):
+ pass