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
from Cython.Utils import UtilityCode
import StringEncoding
import Naming
import Nodes
from Nodes import Node
import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type
......@@ -4233,19 +4234,30 @@ class DivNode(NumBinopNode):
# '/' or '//' operator.
cdivision = None
cdivision_warnings = False
def generate_evaluation_code(self, code):
if not self.type.is_pyobject:
if self.cdivision is None:
self.cdivision = (code.globalstate.directives['cdivision']
or not self.type.signed
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))
NumBinopNode.generate_evaluation_code(self, code)
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)" % (
self.operand1.result(),
self.operand2.result())
......@@ -4256,11 +4268,9 @@ class DivNode(NumBinopNode):
self.operand2.result())
class ModNode(NumBinopNode):
class ModNode(DivNode):
# '%' operator.
cdivision = None
def is_py_operation(self):
return (self.operand1.type.is_string
or self.operand2.type.is_string
......@@ -4270,15 +4280,27 @@ class ModNode(NumBinopNode):
if not self.type.is_pyobject:
if self.cdivision is None:
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:
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))
NumBinopNode.generate_evaluation_code(self, code)
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:
return "fmod%s(%s, %s)" % (
self.type.math_h_modifier,
......@@ -5707,3 +5729,57 @@ static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
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) {
}
#endif
""")
""",
requires=[printing_utility_code])
......
......@@ -62,6 +62,7 @@ option_defaults = {
'locals' : {},
'auto_cpdef': False,
'cdivision': True, # Will be False in 0.12
'cdivision_warnings': False,
}
# Override types possibilities above, if needed
......
......@@ -26,6 +26,13 @@ True
>>> [test_cdiv_cmod(a, b) for a, b in v]
[(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
......@@ -73,3 +80,13 @@ def test_cdiv_cmod(short a, short b):
cdef short q = cython.cdiv(a, b)
cdef short r = cython.cmod(a, b)
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