Commit 9a88d3ca authored by Stefan Behnel's avatar Stefan Behnel

Repair the coercion of C string literals to C++ strings for function...

Repair the coercion of C string literals to C++ strings for function arguments: must create a copy for non-const arguments and can use C++ coercion for const literals.
Closes #2132.
parent d4e15255
...@@ -130,6 +130,10 @@ Bugs fixed ...@@ -130,6 +130,10 @@ Bugs fixed
* Iterator declarations in C++ ``deque`` and ``vector`` were corrected. * Iterator declarations in C++ ``deque`` and ``vector`` were corrected.
Patch by Alex Huszagh. (Github issue #1870) Patch by Alex Huszagh. (Github issue #1870)
* The const modifiers in the C++ ``string`` declarations were corrected, together
with the coercion behaviour of string literals into C++ strings.
(Github issue #2132)
* Some declaration types in ``libc.limits`` were corrected. * Some declaration types in ``libc.limits`` were corrected.
Patch by Jeroen Demeyer. (Github issue #2016) Patch by Jeroen Demeyer. (Github issue #2016)
......
...@@ -1451,8 +1451,10 @@ class BytesNode(ConstNode): ...@@ -1451,8 +1451,10 @@ class BytesNode(ConstNode):
else PyrexTypes.c_char_ptr_type) else PyrexTypes.c_char_ptr_type)
return CastNode(node, dst_type) return CastNode(node, dst_type)
elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type): elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
node.type = dst_type # Exclude the case of passing a C string literal into a non-const C++ string.
return node if not dst_type.is_cpp_class or dst_type.is_const:
node.type = dst_type
return node
# We still need to perform normal coerce_to processing on the # We still need to perform normal coerce_to processing on the
# result, because we might be coercing to an extension type, # result, because we might be coercing to an extension type,
...@@ -5542,8 +5544,6 @@ class SimpleCallNode(CallNode): ...@@ -5542,8 +5544,6 @@ class SimpleCallNode(CallNode):
for i in range(min(max_nargs, actual_nargs)): for i in range(min(max_nargs, actual_nargs)):
formal_arg = func_type.args[i] formal_arg = func_type.args[i]
formal_type = formal_arg.type formal_type = formal_arg.type
if formal_type.is_const:
formal_type = formal_type.const_base_type
arg = args[i].coerce_to(formal_type, env) arg = args[i].coerce_to(formal_type, env)
if formal_arg.not_none: if formal_arg.not_none:
# C methods must do the None checks at *call* time # C methods must do the None checks at *call* time
......
...@@ -9,9 +9,9 @@ cdef extern from "<string>" namespace "std" nogil: ...@@ -9,9 +9,9 @@ cdef extern from "<string>" namespace "std" nogil:
cdef cppclass string: cdef cppclass string:
string() except + string() except +
string(char *) except + string(const char *) except +
string(char *, size_t) except + string(const char *, size_t) except +
string(string&) except + string(const string&) except +
# as a string formed by a repetition of character c, n times. # as a string formed by a repetition of character c, n times.
string(size_t, char) except + string(size_t, char) except +
...@@ -63,65 +63,65 @@ cdef extern from "<string>" namespace "std" nogil: ...@@ -63,65 +63,65 @@ cdef extern from "<string>" namespace "std" nogil:
char& at(size_t) char& at(size_t)
char& operator[](size_t) char& operator[](size_t)
int compare(string&) int compare(const string&)
string& append(string&) string& append(const string&)
string& append(string&, size_t, size_t) string& append(const string&, size_t, size_t)
string& append(char *) string& append(const char *)
string& append(char *, size_t) string& append(const char *, size_t)
string& append(size_t, char) string& append(size_t, char)
void push_back(char c) void push_back(char c)
string& assign (string&) string& assign (const string&)
string& assign (string&, size_t, size_t) string& assign (const string&, size_t, size_t)
string& assign (char *, size_t) string& assign (const char *, size_t)
string& assign (char *) string& assign (const char *)
string& assign (size_t n, char c) string& assign (size_t n, char c)
string& insert(size_t, string&) string& insert(size_t, const string&)
string& insert(size_t, string&, size_t, size_t) string& insert(size_t, const string&, size_t, size_t)
string& insert(size_t, char* s, size_t) string& insert(size_t, const char* s, size_t)
string& insert(size_t, char* s) string& insert(size_t, const char* s)
string& insert(size_t, size_t, char c) string& insert(size_t, size_t, char c)
size_t copy(char *, size_t, size_t) size_t copy(char *, size_t, size_t)
size_t find(string&) size_t find(const string&)
size_t find(string&, size_t) size_t find(const string&, size_t)
size_t find(char*, size_t pos, size_t) size_t find(const char*, size_t pos, size_t)
size_t find(char*, size_t pos) size_t find(const char*, size_t pos)
size_t find(char, size_t pos) size_t find(char, size_t pos)
size_t rfind(string&, size_t) size_t rfind(const string&, size_t)
size_t rfind(char* s, size_t, size_t) size_t rfind(const char* s, size_t, size_t)
size_t rfind(char*, size_t pos) size_t rfind(const char*, size_t pos)
size_t rfind(char c, size_t) size_t rfind(char c, size_t)
size_t rfind(char c) size_t rfind(char c)
size_t find_first_of(string&, size_t) size_t find_first_of(const string&, size_t)
size_t find_first_of(char* s, size_t, size_t) size_t find_first_of(const char* s, size_t, size_t)
size_t find_first_of(char*, size_t pos) size_t find_first_of(const char*, size_t pos)
size_t find_first_of(char c, size_t) size_t find_first_of(char c, size_t)
size_t find_first_of(char c) size_t find_first_of(char c)
size_t find_first_not_of(string&, size_t) size_t find_first_not_of(const string&, size_t)
size_t find_first_not_of(char* s, size_t, size_t) size_t find_first_not_of(const char* s, size_t, size_t)
size_t find_first_not_of(char*, size_t pos) size_t find_first_not_of(const char*, size_t pos)
size_t find_first_not_of(char c, size_t) size_t find_first_not_of(char c, size_t)
size_t find_first_not_of(char c) size_t find_first_not_of(char c)
size_t find_last_of(string&, size_t) size_t find_last_of(const string&, size_t)
size_t find_last_of(char* s, size_t, size_t) size_t find_last_of(const char* s, size_t, size_t)
size_t find_last_of(char*, size_t pos) size_t find_last_of(const char*, size_t pos)
size_t find_last_of(char c, size_t) size_t find_last_of(char c, size_t)
size_t find_last_of(char c) size_t find_last_of(char c)
size_t find_last_not_of(string&, size_t) size_t find_last_not_of(const string&, size_t)
size_t find_last_not_of(char* s, size_t, size_t) size_t find_last_not_of(const char* s, size_t, size_t)
size_t find_last_not_of(char*, size_t pos) size_t find_last_not_of(const char*, size_t pos)
string substr(size_t, size_t) string substr(size_t, size_t)
string substr() string substr()
...@@ -130,27 +130,27 @@ cdef extern from "<string>" namespace "std" nogil: ...@@ -130,27 +130,27 @@ cdef extern from "<string>" namespace "std" nogil:
size_t find_last_not_of(char c, size_t) size_t find_last_not_of(char c, size_t)
size_t find_last_not_of(char c) size_t find_last_not_of(char c)
#string& operator= (string&) #string& operator= (const string&)
#string& operator= (char*) #string& operator= (const char*)
#string& operator= (char) #string& operator= (char)
string operator+ (string& rhs) string operator+ (const string& rhs)
string operator+ (char* rhs) string operator+ (const char* rhs)
bint operator==(string&) bint operator==(const string&)
bint operator==(char*) bint operator==(const char*)
bint operator!= (string& rhs ) bint operator!= (const string& rhs )
bint operator!= (char* ) bint operator!= (const char* )
bint operator< (string&) bint operator< (const string&)
bint operator< (char*) bint operator< (const char*)
bint operator> (string&) bint operator> (const string&)
bint operator> (char*) bint operator> (const char*)
bint operator<= (string&) bint operator<= (const string&)
bint operator<= (char*) bint operator<= (const char*)
bint operator>= (string&) bint operator>= (const string&)
bint operator>= (char*) bint operator>= (const char*)
...@@ -19,5 +19,5 @@ cdef long long e = constructor_overload(17) ...@@ -19,5 +19,5 @@ cdef long long e = constructor_overload(17)
_ERRORS = u""" _ERRORS = u"""
18:40: Cannot assign type 'long' to 'wrapped_int' 18:40: Cannot assign type 'long' to 'const wrapped_int'
""" """
# mode: run # mode: run
# tag: cpp, werror # tag: cpp, warnings
cimport cython cimport cython
...@@ -9,6 +9,40 @@ b_asdf = b'asdf' ...@@ -9,6 +9,40 @@ b_asdf = b'asdf'
b_asdg = b'asdg' b_asdg = b'asdg'
b_s = b's' b_s = b's'
cdef int compare_to_asdf_ref(string& s) except -999:
return s.compare(b"asdf")
def test_coerced_literal_ref():
"""
>>> test_coerced_literal_ref()
0
"""
return compare_to_asdf_ref("asdf")
cdef int compare_to_asdf_const_ref(const string& s) except -999:
return s.compare(b"asdf")
def test_coerced_literal_const_ref():
"""
>>> test_coerced_literal_const_ref()
0
"""
return compare_to_asdf_const_ref("asdf")
cdef int compare_to_asdf_const(const string s) except -999:
return s.compare(b"asdf")
def test_coerced_literal_const():
"""
>>> test_coerced_literal_const()
0
"""
return compare_to_asdf_const("asdf")
def test_conversion(py_obj): def test_conversion(py_obj):
""" """
>>> test_conversion(b_asdf) == b_asdf or test_conversion(b_asdf) >>> test_conversion(b_asdf) == b_asdf or test_conversion(b_asdf)
...@@ -310,3 +344,8 @@ def test_iteration(string s): ...@@ -310,3 +344,8 @@ def test_iteration(string s):
[] []
""" """
return [c for c in s] return [c for c in s]
_WARNINGS = """
21:31: Cannot pass Python object as C++ data structure reference (string &), will pass by copy.
"""
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