Commit 38653119 authored by Stefan Behnel's avatar Stefan Behnel

Fix C++ assignments to references returned by operator[].

Closes #2671.
parent 0347069e
...@@ -4102,7 +4102,7 @@ class IndexNode(_IndexingBaseNode): ...@@ -4102,7 +4102,7 @@ class IndexNode(_IndexingBaseNode):
# both exception handlers are the same. # both exception handlers are the same.
translate_cpp_exception(code, self.pos, translate_cpp_exception(code, self.pos,
"%s = %s;" % (self.result(), rhs.result()), "%s = %s;" % (self.result(), rhs.result()),
self.result() if self.lhs.is_pyobject else None, self.result() if self.type.is_pyobject else None,
self.exception_value, self.in_nogil_context) self.exception_value, self.in_nogil_context)
else: else:
code.putln( code.putln(
......
...@@ -9,48 +9,56 @@ from cython.operator cimport typeid, dereference as deref ...@@ -9,48 +9,56 @@ from cython.operator cimport typeid, dereference as deref
from libc.string cimport const_char from libc.string cimport const_char
from libcpp cimport bool from libcpp cimport bool
cdef out(s, result_type=None): cdef out(s, result_type=None):
print '%s [%s]' % (s.decode('ascii'), result_type) print '%s [%s]' % (s.decode('ascii'), result_type)
cdef iout(int s, result_type=None):
print '%s [%s]' % (s, result_type)
cdef extern from "cpp_operators_helper.h" nogil: cdef extern from "cpp_operators_helper.h" nogil:
cdef cppclass TestOps: cdef cppclass TestOps:
const_char* operator+() const_char* operator+() except +
const_char* operator-() const_char* operator-() except +
const_char* operator*() const_char* operator*() except +
const_char* operator~() const_char* operator~() except +
const_char* operator!() const_char* operator!() except +
# FIXME: using 'except +' here leads to wrong calls ???
const_char* operator++() const_char* operator++()
const_char* operator--() const_char* operator--()
const_char* operator++(int) const_char* operator++(int)
const_char* operator--(int) const_char* operator--(int)
const_char* operator+(int) const_char* operator+(int) except +
const_char* operator+(int,const TestOps&) const_char* operator+(int,const TestOps&) except +
const_char* operator-(int) const_char* operator-(int) except +
const_char* operator-(int,const TestOps&) const_char* operator-(int,const TestOps&) except +
const_char* operator*(int) const_char* operator*(int) except +
# deliberately omitted operator* to test case where only defined outside class # deliberately omitted operator* to test case where only defined outside class
const_char* operator/(int) const_char* operator/(int) except +
const_char* operator/(int,const TestOps&) const_char* operator/(int,const TestOps&) except +
const_char* operator%(int) const_char* operator%(int) except +
const_char* operator%(int,const TestOps&) const_char* operator%(int,const TestOps&) except +
const_char* operator|(int) const_char* operator|(int) except +
const_char* operator|(int,const TestOps&) const_char* operator|(int,const TestOps&) except +
const_char* operator&(int) const_char* operator&(int) except +
const_char* operator&(int,const TestOps&) const_char* operator&(int,const TestOps&) except +
const_char* operator^(int) const_char* operator^(int) except +
const_char* operator^(int,const TestOps&) const_char* operator^(int,const TestOps&) except +
const_char* operator,(int) const_char* operator,(int) except +
const_char* operator,(int,const TestOps&) const_char* operator,(int,const TestOps&) except +
const_char* operator<<(int) const_char* operator<<(int) except +
const_char* operator<<(int,const TestOps&) const_char* operator<<(int,const TestOps&) except +
const_char* operator>>(int) const_char* operator>>(int) except +
const_char* operator>>(int,const TestOps&) const_char* operator>>(int,const TestOps&) except +
# FIXME: using 'except +' here leads to invalid C++ code ???
const_char* operator==(int) const_char* operator==(int)
const_char* operator!=(int) const_char* operator!=(int)
const_char* operator>=(int) const_char* operator>=(int)
...@@ -58,25 +66,73 @@ cdef extern from "cpp_operators_helper.h" nogil: ...@@ -58,25 +66,73 @@ cdef extern from "cpp_operators_helper.h" nogil:
const_char* operator>(int) const_char* operator>(int)
const_char* operator<(int) const_char* operator<(int)
const_char* operator[](int) const_char* operator[](int) except +
const_char* operator()(int) const_char* operator()(int) except +
# Defining the operator outside the class does work # Defining the operator outside the class does work
# but doesn't help when importing from pxd files # but doesn't help when importing from pxd files
# (they don't get imported) # (they don't get imported)
const_char* operator+(float,const TestOps&) const_char* operator+(float,const TestOps&) except +
# deliberately omitted operator- to test case where only defined in class # deliberately omitted operator- to test case where only defined in class
const_char* operator*(float,const TestOps&) const_char* operator*(float,const TestOps&) except +
const_char* operator/(float,const TestOps&) const_char* operator/(float,const TestOps&) except +
const_char* operator%(float,const TestOps&) const_char* operator%(float,const TestOps&) except +
const_char* operator|(float,const TestOps&) const_char* operator|(float,const TestOps&) except +
const_char* operator&(float,const TestOps&) const_char* operator&(float,const TestOps&) except +
const_char* operator^(float,const TestOps&) const_char* operator^(float,const TestOps&) except +
const_char* operator,(float,const TestOps&) const_char* operator,(float,const TestOps&) except +
const_char* operator<<(float,const TestOps&) const_char* operator<<(float,const TestOps&) except +
const_char* operator>>(float,const TestOps&) const_char* operator>>(float,const TestOps&) except +
cdef cppclass RefTestOps:
int& operator+() except +
int& operator-() except +
int& operator*() except +
int& operator~() except +
int& operator!() except +
int& operator++() except +
int& operator--() except +
int& operator++(int) except +
int& operator--(int) except +
int& operator+(int) except +
int& operator+(int,const TestOps&) except +
int& operator-(int) except +
int& operator-(int,const TestOps&) except +
int& operator*(int) except +
# deliberately omitted operator* to test case where only defined outside class
int& operator/(int) except +
int& operator/(int,const TestOps&) except +
int& operator%(int) except +
int& operator%(int,const TestOps&) except +
int& operator|(int) except +
int& operator|(int,const TestOps&) except +
int& operator&(int) except +
int& operator&(int,const TestOps&) except +
int& operator^(int) except +
int& operator^(int,const TestOps&) except +
int& operator,(int) except +
int& operator,(int,const TestOps&) except +
int& operator<<(int) except +
int& operator<<(int,const TestOps&) except +
int& operator>>(int) except +
int& operator>>(int,const TestOps&) except +
int& operator==(int) except +
int& operator!=(int) except +
int& operator>=(int) except +
int& operator<=(int) except +
int& operator>(int) except +
int& operator<(int) except +
int& operator[](int) except +
int& operator()(int) except +
cdef cppclass TruthClass: cdef cppclass TruthClass:
TruthClass() TruthClass()
...@@ -84,9 +140,11 @@ cdef extern from "cpp_operators_helper.h" nogil: ...@@ -84,9 +140,11 @@ cdef extern from "cpp_operators_helper.h" nogil:
bool operator bool() bool operator bool()
bool value bool value
cdef cppclass TruthSubClass(TruthClass): cdef cppclass TruthSubClass(TruthClass):
pass pass
def test_unops(): def test_unops():
""" """
>>> test_unops() >>> test_unops()
...@@ -233,6 +291,7 @@ def test_cmp(): ...@@ -233,6 +291,7 @@ def test_cmp():
out(t[0] < 1, typeof(t[0] < 1)) out(t[0] < 1, typeof(t[0] < 1))
del t del t
def test_index_call(): def test_index_call():
""" """
>>> test_index_call() >>> test_index_call()
...@@ -244,6 +303,20 @@ def test_index_call(): ...@@ -244,6 +303,20 @@ def test_index_call():
out(t[0](100), typeof(t[0](100))) out(t[0](100), typeof(t[0](100)))
del t del t
def test_index_assignment():
"""
>>> test_index_assignment()
0 [int &]
123 [int [&]]
"""
cdef RefTestOps* t = new RefTestOps()
iout(t[0][100], typeof(t[0][100]))
t[0][99] = 123
iout(t[0](100), typeof(t[0](100)))
del t
def test_bool_op(): def test_bool_op():
""" """
>>> test_bool_op() >>> test_bool_op()
......
...@@ -76,6 +76,58 @@ NONMEMBER_BIN_OP2(&) ...@@ -76,6 +76,58 @@ NONMEMBER_BIN_OP2(&)
NONMEMBER_BIN_OP2(^) NONMEMBER_BIN_OP2(^)
NONMEMBER_BIN_OP2(COMMA) NONMEMBER_BIN_OP2(COMMA)
/* RefTestOps */
#define REF_UN_OP(op) int& operator op () { return value; }
#define REF_POST_UN_OP(op) int& operator op (int x) { x++; return value; }
#define REF_BIN_OP(op) int& operator op (int x) { x++; return value; }
class RefTestOps {
int value = 0;
public:
REF_UN_OP(-);
REF_UN_OP(+);
REF_UN_OP(*);
REF_UN_OP(~);
REF_UN_OP(!);
REF_UN_OP(&);
REF_UN_OP(++);
REF_UN_OP(--);
REF_POST_UN_OP(++);
REF_POST_UN_OP(--);
REF_BIN_OP(+);
REF_BIN_OP(-);
REF_BIN_OP(*);
REF_BIN_OP(/);
REF_BIN_OP(%);
REF_BIN_OP(<<);
REF_BIN_OP(>>);
REF_BIN_OP(|);
REF_BIN_OP(&);
REF_BIN_OP(^);
REF_BIN_OP(COMMA);
REF_BIN_OP(==);
REF_BIN_OP(!=);
REF_BIN_OP(<=);
REF_BIN_OP(<);
REF_BIN_OP(>=);
REF_BIN_OP(>);
REF_BIN_OP([]);
REF_BIN_OP(());
};
/* TruthClass */
class TruthClass { class TruthClass {
public: public:
TruthClass() : value(false) {} TruthClass() : value(false) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment