Commit 3c3e4564 authored by Stefan Behnel's avatar Stefan Behnel

reduce impact of 'unsafe C derivative' error to pointers and fix conditional expressions

parent eb637f5e
...@@ -9755,6 +9755,9 @@ class CondExprNode(ExprNode): ...@@ -9755,6 +9755,9 @@ class CondExprNode(ExprNode):
else: else:
self.constant_result = self.false_val.constant_result self.constant_result = self.false_val.constant_result
def is_ephemeral(self):
return self.true_val.is_ephemeral() or self.false_val.is_ephemeral()
def analyse_types(self, env): def analyse_types(self, env):
self.test = self.test.analyse_types(env).coerce_to_boolean(env) self.test = self.test.analyse_types(env).coerce_to_boolean(env)
self.true_val = self.true_val.analyse_types(env) self.true_val = self.true_val.analyse_types(env)
...@@ -9767,6 +9770,8 @@ class CondExprNode(ExprNode): ...@@ -9767,6 +9770,8 @@ class CondExprNode(ExprNode):
self.true_val.type, self.false_val.type) self.true_val.type, self.false_val.type)
if self.type.is_pyobject: if self.type.is_pyobject:
self.result_ctype = py_object_type self.result_ctype = py_object_type
elif self.true_val.is_ephemeral() or self.false_val.is_ephemeral():
error(self.pos, "Unsafe C derivative of temporary Python reference used in conditional expression")
if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject: if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
self.true_val = self.true_val.coerce_to(self.type, env) self.true_val = self.true_val.coerce_to(self.type, env)
self.false_val = self.false_val.coerce_to(self.type, env) self.false_val = self.false_val.coerce_to(self.type, env)
...@@ -9798,7 +9803,7 @@ class CondExprNode(ExprNode): ...@@ -9798,7 +9803,7 @@ class CondExprNode(ExprNode):
code.mark_pos(self.pos) code.mark_pos(self.pos)
self.allocate_temp_result(code) self.allocate_temp_result(code)
self.test.generate_evaluation_code(code) self.test.generate_evaluation_code(code)
code.putln("if (%s) {" % self.test.result() ) code.putln("if (%s) {" % self.test.result())
self.eval_and_get(code, self.true_val) self.eval_and_get(code, self.true_val)
code.putln("} else {") code.putln("} else {")
self.eval_and_get(code, self.false_val) self.eval_and_get(code, self.false_val)
...@@ -9813,6 +9818,13 @@ class CondExprNode(ExprNode): ...@@ -9813,6 +9818,13 @@ class CondExprNode(ExprNode):
expr.generate_post_assignment_code(code) expr.generate_post_assignment_code(code)
expr.free_temps(code) expr.free_temps(code)
def generate_subexpr_disposal_code(self, code):
pass # done explicitly above (cleanup must separately happen within the if/else blocks)
def free_subexpr_temps(self, code):
pass # done explicitly above (cleanup must separately happen within the if/else blocks)
richcmp_constants = { richcmp_constants = {
"<" : "Py_LT", "<" : "Py_LT",
"<=": "Py_LE", "<=": "Py_LE",
......
...@@ -4559,7 +4559,7 @@ class AssignmentNode(StatNode): ...@@ -4559,7 +4559,7 @@ class AssignmentNode(StatNode):
def analyse_expressions(self, env): def analyse_expressions(self, env):
node = self.analyse_types(env) node = self.analyse_types(env)
if isinstance(node, AssignmentNode): if isinstance(node, AssignmentNode):
if not node.rhs.type.is_pyobject and node.rhs.is_ephemeral(): if node.rhs.type.is_ptr and node.rhs.is_ephemeral():
error(self.pos, "Storing unsafe C derivative of temporary Python reference") error(self.pos, "Storing unsafe C derivative of temporary Python reference")
return node return node
......
...@@ -44,6 +44,14 @@ cuptr = u ...@@ -44,6 +44,14 @@ cuptr = u
cuptr = u + u"cba" cuptr = u + u"cba"
# coercion in conditional expression => ok
boolval = list(u)
cptr = c_s if boolval else c_s
# temp in conditional expression => error
cptr = s + b'x' if boolval else s + b'y'
_ERRORS = """ _ERRORS = """
16:8: Obtaining 'char *' from externally modifiable global Python value 16:8: Obtaining 'char *' from externally modifiable global Python value
19:9: Storing unsafe C derivative of temporary Python reference 19:9: Storing unsafe C derivative of temporary Python reference
...@@ -53,4 +61,6 @@ _ERRORS = """ ...@@ -53,4 +61,6 @@ _ERRORS = """
26:8: Storing unsafe C derivative of temporary Python reference 26:8: Storing unsafe C derivative of temporary Python reference
41:9: Obtaining 'Py_UNICODE *' from externally modifiable global Python value 41:9: Obtaining 'Py_UNICODE *' from externally modifiable global Python value
44:10: Storing unsafe C derivative of temporary Python reference 44:10: Storing unsafe C derivative of temporary Python reference
52:7: Storing unsafe C derivative of temporary Python reference
52:7: Unsafe C derivative of temporary Python reference used in conditional expression
""" """
...@@ -40,5 +40,5 @@ def test_charptr_coercion(x): ...@@ -40,5 +40,5 @@ def test_charptr_coercion(x):
>>> print(test_charptr_coercion(False)) >>> print(test_charptr_coercion(False))
def def
""" """
cdef char* s = 'abc' if x else 'def' cdef char* s = b'abc' if x else b'def'
return s.decode('ascii') return s.decode('ascii')
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