let += and -= inplace operators use pointer arithmetic when used on C strings (instea...
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Nov 2013 20:59:15 +0000 (21:59 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Nov 2013 20:59:15 +0000 (21:59 +0100)
Cython/Compiler/Nodes.py
tests/compile/inplace_ops.pyx
tests/run/bytes_char_coercion.pyx

index 919bdc2..ba1e7e9 100644 (file)
@@ -4716,6 +4716,9 @@ class InPlaceAssignmentNode(AssignmentNode):
         if (self.lhs.is_subscript and
                 (self.lhs.memslice_index or self.lhs.is_buffer_access)):
             self.rhs = self.rhs.coerce_to(self.lhs.type, env)
+        elif self.lhs.type.is_string and self.operator in '+-':
+            # use pointer arithmetic for char* LHS instead of string concat
+            self.rhs = self.rhs.coerce_to(PyrexTypes.c_py_ssize_t_type, env)
         return self
 
     def generate_execution_code(self, code):
index e792b2d..354202a 100644 (file)
@@ -16,4 +16,4 @@ def test():
     a |= b
     p += 42
     p -= 42
-    #p += a     # FIXME: should use pointer arithmetic, not string concat
+    p += a
index 82c63e7..ed3db06 100644 (file)
@@ -152,3 +152,17 @@ def coerce_uint_bytes_assign(unsigned int c):
     """
     cdef bytes s = c
     return s
+
+
+def inplace_ops_use_arithmetic():
+    """
+    >>> print(inplace_ops_use_arithmetic().decode('ascii'))
+    bc
+    """
+    cdef char* s = 'abc'
+    cdef object x = 1
+    s += 1
+    s += 2*x
+    s -= 1
+    s -= x
+    return s