changelog shortlog tags browse all files raw

changeset: nonecheck directive for buffer accesses

changeset 1177: 06bcb482828a
parent 1176:420995471deb
child 1181:4bde563221e2
author: Dag Sverre Seljebotn <dagss@student.matnat.uio.no>
date: Thu Sep 25 18:33:27 2008 +0200 (3 months ago)
files: Cython/Compiler/ExprNodes.py tests/run/nonecheck.pyx
description: nonecheck directive for buffer accesses
--- a/Cython/Compiler/ExprNodes.py	Tue Sep 23 13:55:49 2008 -0700
+++ b/Cython/Compiler/ExprNodes.py	Thu Sep 25 18:33:27 2008 +0200
@@ -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
@@ -1606,6 +1610,13 @@ class IndexNode(ExprNode):
                                              index_cnames=index_temps,
                                              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_RaiseNoneAttrib
     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");
+}
+"""]
--- a/tests/run/nonecheck.pyx	Tue Sep 23 13:55:49 2008 -0700
+++ b/tests/run/nonecheck.pyx	Thu Sep 25 18:33:27 2008 +0200
@@ -31,6 +31,16 @@ Traceback (most recent call last):
 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
 
 """
 
@@ -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
+