Commit 43ba295b authored by Robert Bradshaw's avatar Robert Bradshaw

CDP 516 warnings

parent 33784d77
...@@ -9,6 +9,7 @@ from Errors import hold_errors, release_errors, held_errors, report_error ...@@ -9,6 +9,7 @@ from Errors import hold_errors, release_errors, held_errors, report_error
from Cython.Utils import UtilityCode from Cython.Utils import UtilityCode
import StringEncoding import StringEncoding
import Naming import Naming
import Nodes
from Nodes import Node from Nodes import Node
import PyrexTypes import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type from PyrexTypes import py_object_type, c_long_type, typecast, error_type
...@@ -4233,6 +4234,7 @@ class DivNode(NumBinopNode): ...@@ -4233,6 +4234,7 @@ class DivNode(NumBinopNode):
# '/' or '//' operator. # '/' or '//' operator.
cdivision = None cdivision = None
cdivision_warnings = False
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
if not self.type.is_pyobject: if not self.type.is_pyobject:
...@@ -4240,12 +4242,22 @@ class DivNode(NumBinopNode): ...@@ -4240,12 +4242,22 @@ class DivNode(NumBinopNode):
self.cdivision = (code.globalstate.directives['cdivision'] self.cdivision = (code.globalstate.directives['cdivision']
or not self.type.signed or not self.type.signed
or self.type.is_float) or self.type.is_float)
if not self.cdivision: if code.globalstate.directives['cdivision_warnings']:
self.cdivision_warnings = True
code.globalstate.use_utility_code(div_mod_print_warning_utility_code)
code.globalstate.use_utility_code(div_warn_utility_code.specialize(self.type))
elif not self.cdivision:
code.globalstate.use_utility_code(div_utility_code.specialize(self.type)) code.globalstate.use_utility_code(div_utility_code.specialize(self.type))
NumBinopNode.generate_evaluation_code(self, code) NumBinopNode.generate_evaluation_code(self, code)
def calculate_result_code(self): def calculate_result_code(self):
if self.cdivision: if self.cdivision_warnings:
return "__Pyx_div_warn_%s(%s, %s, %s)" % (
self.type.specalization_name(),
self.operand1.result(),
self.operand2.result(),
int(self.cdivision))
elif self.cdivision:
return "(%s / %s)" % ( return "(%s / %s)" % (
self.operand1.result(), self.operand1.result(),
self.operand2.result()) self.operand2.result())
...@@ -4256,11 +4268,9 @@ class DivNode(NumBinopNode): ...@@ -4256,11 +4268,9 @@ class DivNode(NumBinopNode):
self.operand2.result()) self.operand2.result())
class ModNode(NumBinopNode): class ModNode(DivNode):
# '%' operator. # '%' operator.
cdivision = None
def is_py_operation(self): def is_py_operation(self):
return (self.operand1.type.is_string return (self.operand1.type.is_string
or self.operand2.type.is_string or self.operand2.type.is_string
...@@ -4270,15 +4280,27 @@ class ModNode(NumBinopNode): ...@@ -4270,15 +4280,27 @@ class ModNode(NumBinopNode):
if not self.type.is_pyobject: if not self.type.is_pyobject:
if self.cdivision is None: if self.cdivision is None:
self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
if not self.cdivision:
math_h_modifier = getattr(self.type, 'math_h_modifier', '__Pyx_INT') math_h_modifier = getattr(self.type, 'math_h_modifier', '__Pyx_INT')
if code.globalstate.directives['cdivision_warnings']:
self.cdivision_warnings = True
if self.type.is_int:
code.globalstate.use_utility_code(mod_int_helper_macro)
code.globalstate.use_utility_code(div_mod_print_warning_utility_code)
code.globalstate.use_utility_code(mod_warn_utility_code.specialize(self.type, math_h_modifier=math_h_modifier))
elif not self.cdivision:
if self.type.is_int: if self.type.is_int:
code.globalstate.use_utility_code(mod_int_helper_macro) code.globalstate.use_utility_code(mod_int_helper_macro)
code.globalstate.use_utility_code(mod_utility_code.specialize(self.type, math_h_modifier=math_h_modifier)) code.globalstate.use_utility_code(mod_utility_code.specialize(self.type, math_h_modifier=math_h_modifier))
NumBinopNode.generate_evaluation_code(self, code) NumBinopNode.generate_evaluation_code(self, code)
def calculate_result_code(self): def calculate_result_code(self):
if self.cdivision: if self.cdivision_warnings:
return "__Pyx_mod_warn_%s(%s, %s, %s)" % (
self.type.specalization_name(),
self.operand1.result(),
self.operand2.result(),
int(self.cdivision))
elif self.cdivision:
if self.type.is_float: if self.type.is_float:
return "fmod%s(%s, %s)" % ( return "fmod%s(%s, %s)" % (
self.type.math_h_modifier, self.type.math_h_modifier,
...@@ -5707,3 +5729,57 @@ static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) { ...@@ -5707,3 +5729,57 @@ static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
return res; return res;
} }
""") """)
mod_warn_utility_code = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_mod_warn_%(type_name)s(%(type)s, %(type)s, int cdivision); /* proto */
""",
impl="""
static INLINE %(type)s __Pyx_mod_warn_%(type_name)s(%(type)s a, %(type)s b, int cdivision) {
%(type)s res = fmod%(math_h_modifier)s(a, b);
if (res * b < 0) {
__Pyx_div_mod_warning();
if (!cdivision) res += b;
}
return res;
}
""")
div_warn_utility_code = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_div_warn_%(type_name)s(%(type)s, %(type)s, int cdivision); /* proto */
""",
impl="""
static INLINE %(type)s __Pyx_div_warn_%(type_name)s(%(type)s a, %(type)s b, int cdivision) {
%(type)s res = a / b;
if (res < 0) {
if (__Pyx_div_mod_warning()) ;
if (!cdivision) res -= 1;
}
return res;
}
""")
div_mod_print_warning_utility_code = UtilityCode(
proto="""
static int __Pyx_div_mod_warning(void); /* proto */
""",
impl="""
static int __Pyx_div_mod_warning(void) {
int r;
PyObject* s;
#if PY_MAJOR_VERSION < 3
s = PyString_FromString("Warning: division with oppositely signed operands, C and Python semantics differ");
#else
s = PyUnicode_FromString("Warning: division with oppositely signed operands, C and Python semantics differ");
#endif
if (s) {
r = __Pyx_PrintOne(s);
Py_DECREF(s);
}
else r = -1;
return r;
}
""",
requires=[Nodes.printing_one_utility_code])
...@@ -4976,7 +4976,8 @@ static int __Pyx_PrintOne(PyObject *o) { ...@@ -4976,7 +4976,8 @@ static int __Pyx_PrintOne(PyObject *o) {
} }
#endif #endif
""") """,
requires=[printing_utility_code])
......
...@@ -62,6 +62,7 @@ option_defaults = { ...@@ -62,6 +62,7 @@ option_defaults = {
'locals' : {}, 'locals' : {},
'auto_cpdef': False, 'auto_cpdef': False,
'cdivision': True, # Will be False in 0.12 'cdivision': True, # Will be False in 0.12
'cdivision_warnings': False,
} }
# Override types possibilities above, if needed # Override types possibilities above, if needed
......
...@@ -26,6 +26,13 @@ True ...@@ -26,6 +26,13 @@ True
>>> [test_cdiv_cmod(a, b) for a, b in v] >>> [test_cdiv_cmod(a, b) for a, b in v]
[(1, 7), (-1, -7), (1, -7), (-1, 7)] [(1, 7), (-1, -7), (1, -7), (-1, 7)]
>>> mod_int_py_warn(-17, 10)
Warning: division with oppositely signed operands, C and Python semantics differ
-7
>>> div_int_py_warn(-17, 10)
Warning: division with oppositely signed operands, C and Python semantics differ
-1
""" """
cimport cython cimport cython
...@@ -73,3 +80,13 @@ def test_cdiv_cmod(short a, short b): ...@@ -73,3 +80,13 @@ def test_cdiv_cmod(short a, short b):
cdef short q = cython.cdiv(a, b) cdef short q = cython.cdiv(a, b)
cdef short r = cython.cmod(a, b) cdef short r = cython.cmod(a, b)
return q, r return q, r
@cython.cdivision(True)
@cython.cdivision_warnings(True)
def mod_int_py_warn(int a, int b):
return a % b
@cython.cdivision(True)
@cython.cdivision_warnings(True)
def div_int_py_warn(int a, int b):
return a // b
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