From 622d6734a125f83e40733bdc21d47a7c9c8bd2de Mon Sep 17 00:00:00 2001 From: Vitja Makarov Date: Thu, 23 May 2013 19:56:19 +0400 Subject: [PATCH] Fix external reference assignment --- Cython/Compiler/Code.py | 6 ++++++ Cython/Compiler/ExprNodes.py | 18 +++++++++++++----- Cython/Utility/ModuleSetupCode.c | 9 +++++++++ tests/run/external_ref_reassignment.pyx | 26 ++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/run/external_ref_reassignment.pyx diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 88df66a..b2382e1 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -1738,6 +1738,12 @@ class CCodeWriter(object): self.putln("%s_%sDECREF(%s);" % ( prefix, X, self.as_pyobject(cname, type))) + def put_decref_set(self, cname, rhs_cname): + self.putln("__Pyx_DECREF_SET(%s, %s);" % (cname, rhs_cname)) + + def put_xdecref_set(self, cname, rhs_cname): + self.putln("__Pyx_XDECREF_SET(%s, %s);" % (cname, rhs_cname)) + def put_var_decref(self, entry): if entry.type.is_pyobject: self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry)) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index f11c73a..bc8cb0e 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1883,7 +1883,7 @@ class NameNode(AtomicExprNode): # variables that the acquired buffer info is stored to is allocated # per entry and coupled with it. self.generate_acquire_buffer(rhs, code) - + assigned = False if self.type.is_pyobject: #print "NameNode.generate_assignment_code: to", self.name ### #print "...from", rhs ### @@ -1898,18 +1898,26 @@ class NameNode(AtomicExprNode): code.put_xgotref(self.py_result()) else: code.put_gotref(self.py_result()) + assigned = True if entry.is_cglobal: - code.put_decref(self.result(), self.ctype()) + code.put_decref_set( + self.result(), rhs.result_as(self.ctype())) else: if not self.cf_is_null: if self.cf_maybe_null: - code.put_xdecref(self.result(), self.ctype()) + code.put_xdecref_set( + self.result(), rhs.result_as(self.ctype())) else: - code.put_decref(self.result(), self.ctype()) + code.put_decref_set( + self.result(), rhs.result_as(self.ctype())) + else: + assigned = False if is_external_ref: code.put_giveref(rhs.py_result()) if not self.type.is_memoryviewslice: - code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype()))) + if not assigned: + code.putln('%s = %s;' % ( + self.result(), rhs.result_as(self.ctype()))) if debug_disposal_code: print("NameNode.generate_assignment_code:") print("...generating post-assignment code for %s" % rhs) diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c index 13d4418..c0c59f6 100644 --- a/Cython/Utility/ModuleSetupCode.c +++ b/Cython/Utility/ModuleSetupCode.c @@ -531,6 +531,15 @@ static int __Pyx_check_binary_version(void) { #define __Pyx_XGIVEREF(r) #endif /* CYTHON_REFNANNY */ +#define __Pyx_XDECREF_SET(r, v) do { \ + PyObject *tmp = (PyObject *) r; \ + r = v; __Pyx_XDECREF(tmp); \ + } while (0) +#define __Pyx_DECREF_SET(r, v) do { \ + PyObject *tmp = (PyObject *) r; \ + r = v; __Pyx_DECREF(tmp); \ + } while (0) + #define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) diff --git a/tests/run/external_ref_reassignment.pyx b/tests/run/external_ref_reassignment.pyx new file mode 100644 index 0000000..2927d4a --- /dev/null +++ b/tests/run/external_ref_reassignment.pyx @@ -0,0 +1,26 @@ +# Test that variable visible outside of the local scope (e.g. closure, cglobals) +# is set before original value is decrefed. +cdef object g + +def test_cglobals_reassignment(): + """ + >>> test_cglobals_reassignment() + 1234 + """ + global g + class Special: + def __del__(self): + print g + g = (Special(),) + g = 1234 + +def test_closure_reassignment(): + """ + >>> test_closure_reassignment() + 4321 + """ + class Special: + def __del__(self): + print c + c = (Special(),) + c = 4321 -- 2.7.4