nonecheck directive for buffer accesses
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 25 Sep 2008 16:33:27 +0000 (18:33 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 25 Sep 2008 16:33:27 +0000 (18:33 +0200)
Cython/Compiler/ExprNodes.py
tests/run/nonecheck.pyx

index cd9a5a46151688c19d29ab713fbf9a38de7c282e..2c7aaf4404380c862b8960a11dde67e9506987a1 100644 (file)
@@ -1498,6 +1498,8 @@ class IndexNode(ExprNode):
 
     def generate_result_code(self, code):
         if self.is_buffer_access:
+            if code.globalstate.directives['nonecheck']:
+                self.put_nonecheck(code)
             ptrcode = self.buffer_lookup_code(code)
             code.putln("%s = *%s;" % (
                 self.result(),
@@ -1541,6 +1543,8 @@ class IndexNode(ExprNode):
 
     def generate_buffer_setitem_code(self, rhs, code, op=""):
         # Used from generate_assignment_code and InPlaceAssignmentNode
+        if code.globalstate.directives['nonecheck']:
+            self.put_nonecheck(code)
         ptrexpr = self.buffer_lookup_code(code)
         if self.buffer_type.dtype.is_pyobject:
             # Must manage refcounts. Decref what is already there
@@ -1607,6 +1611,13 @@ class IndexNode(ExprNode):
                                              options=code.globalstate.directives,
                                              pos=self.pos, code=code)
 
+    def put_nonecheck(self, code):
+        code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
+        code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
+        code.putln("__Pyx_RaiseNoneIndexingError();")
+        code.putln(code.error_goto(self.pos))
+        code.putln("}")
+
 class SliceIndexNode(ExprNode):
     #  2-element slice indexing
     #
@@ -4587,3 +4598,12 @@ static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
 }
 """]
+
+raise_noneindex_error_utility_code = [
+"""
+static INLINE void __Pyx_RaiseNoneIndexingError();
+""", """
+static INLINE void __Pyx_RaiseNoneIndexingError() {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
+}
+"""]
index 7645acd03d379722e31c43576e03b813f210c8e5..79ba6f101b2d51d46d38d329db14124757fc7240 100644 (file)
@@ -32,6 +32,16 @@ Traceback (most recent call last):
    ...
 AttributeError: 'NoneType' object has no attribute 'a'
 
+>>> check_buffer_get(None)
+Traceback (most recent call last):
+   ...
+TypeError: 'NoneType' object is unsubscriptable
+
+>>> check_buffer_set(None)
+Traceback (most recent call last):
+   ...
+TypeError: 'NoneType' object is unsubscriptable
+
 """
 
 cimport cython
@@ -70,3 +80,11 @@ def check_and_assign(MyClass var):
         var = None
         print var.a
 
+@cython.nonecheck(True)
+def check_buffer_get(object[int] buf):
+    return buf[0]
+
+@cython.nonecheck(True)
+def check_buffer_set(object[int] buf):
+    buf[0] = 1
+