]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-116417: Avoid PyFloat_AS_DOUBLE() in AC limited C API (#116568)
authorVictor Stinner <vstinner@python.org>
Sun, 10 Mar 2024 19:42:40 +0000 (20:42 +0100)
committerGitHub <noreply@github.com>
Sun, 10 Mar 2024 19:42:40 +0000 (20:42 +0100)
Argument Clinic no longer calls PyFloat_AS_DOUBLE() when the usage of
the limited C API is requested.

Modules/_testclinic_limited.c
Modules/clinic/_testclinic_limited.c.h
Tools/clinic/clinic.py

index ef595be0b626db8fd45f0181a5396da495fb1d04..df08ff9a369b1f94e93b6db85e4e0d68754de869 100644 (file)
@@ -72,10 +72,46 @@ my_int_sum_impl(PyObject *module, int x, int y)
 }
 
 
+/*[clinic input]
+my_float_sum -> float
+
+    x: float
+    y: float
+    /
+
+[clinic start generated code]*/
+
+static float
+my_float_sum_impl(PyObject *module, float x, float y)
+/*[clinic end generated code: output=634f59a5a419cad7 input=d4b5313bdf4dc377]*/
+{
+    return x + y;
+}
+
+
+/*[clinic input]
+my_double_sum -> double
+
+    x: double
+    y: double
+    /
+
+[clinic start generated code]*/
+
+static double
+my_double_sum_impl(PyObject *module, double x, double y)
+/*[clinic end generated code: output=a75576d9e4d8557f input=16b11c8aba172801]*/
+{
+    return x + y;
+}
+
+
 static PyMethodDef tester_methods[] = {
     TEST_EMPTY_FUNCTION_METHODDEF
     MY_INT_FUNC_METHODDEF
     MY_INT_SUM_METHODDEF
+    MY_FLOAT_SUM_METHODDEF
+    MY_DOUBLE_SUM_METHODDEF
     {NULL, NULL}
 };
 
index eff72cee24975c229a0df2cd0646590d96ae1c43..690e782b839cb5208fbc219dba4dbfbd38afd121 100644 (file)
@@ -91,4 +91,86 @@ my_int_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=5cf64baf978d2288 input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(my_float_sum__doc__,
+"my_float_sum($module, x, y, /)\n"
+"--\n"
+"\n");
+
+#define MY_FLOAT_SUM_METHODDEF    \
+    {"my_float_sum", (PyCFunction)(void(*)(void))my_float_sum, METH_FASTCALL, my_float_sum__doc__},
+
+static float
+my_float_sum_impl(PyObject *module, float x, float y);
+
+static PyObject *
+my_float_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    float x;
+    float y;
+    float _return_value;
+
+    if (nargs != 2) {
+        PyErr_Format(PyExc_TypeError, "my_float_sum expected 2 arguments, got %zd", nargs);
+        goto exit;
+    }
+    x = (float) PyFloat_AsDouble(args[0]);
+    if (x == -1.0 && PyErr_Occurred()) {
+        goto exit;
+    }
+    y = (float) PyFloat_AsDouble(args[1]);
+    if (y == -1.0 && PyErr_Occurred()) {
+        goto exit;
+    }
+    _return_value = my_float_sum_impl(module, x, y);
+    if ((_return_value == -1.0) && PyErr_Occurred()) {
+        goto exit;
+    }
+    return_value = PyFloat_FromDouble((double)_return_value);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(my_double_sum__doc__,
+"my_double_sum($module, x, y, /)\n"
+"--\n"
+"\n");
+
+#define MY_DOUBLE_SUM_METHODDEF    \
+    {"my_double_sum", (PyCFunction)(void(*)(void))my_double_sum, METH_FASTCALL, my_double_sum__doc__},
+
+static double
+my_double_sum_impl(PyObject *module, double x, double y);
+
+static PyObject *
+my_double_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    double x;
+    double y;
+    double _return_value;
+
+    if (nargs != 2) {
+        PyErr_Format(PyExc_TypeError, "my_double_sum expected 2 arguments, got %zd", nargs);
+        goto exit;
+    }
+    x = PyFloat_AsDouble(args[0]);
+    if (x == -1.0 && PyErr_Occurred()) {
+        goto exit;
+    }
+    y = PyFloat_AsDouble(args[1]);
+    if (y == -1.0 && PyErr_Occurred()) {
+        goto exit;
+    }
+    _return_value = my_double_sum_impl(module, x, y);
+    if ((_return_value == -1.0) && PyErr_Occurred()) {
+        goto exit;
+    }
+    return_value = PyFloat_FromDouble(_return_value);
+
+exit:
+    return return_value;
+}
+/*[clinic end generated code: output=bb9f6b8c5d9e6a79 input=a9049054013a1b77]*/
index 0a8546247cc326585aac936b301b753d0e62bc62..8353941f929eb1b3c63d56512e05b35ae7045d73 100755 (executable)
@@ -3867,19 +3867,28 @@ class float_converter(CConverter):
 
     def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
         if self.format_unit == 'f':
-            return self.format_code("""
-                if (PyFloat_CheckExact({argname})) {{{{
-                    {paramname} = (float) (PyFloat_AS_DOUBLE({argname}));
-                }}}}
-                else
-                {{{{
+            if not limited_capi:
+                return self.format_code("""
+                    if (PyFloat_CheckExact({argname})) {{{{
+                        {paramname} = (float) (PyFloat_AS_DOUBLE({argname}));
+                    }}}}
+                    else
+                    {{{{
+                        {paramname} = (float) PyFloat_AsDouble({argname});
+                        if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
+                            goto exit;
+                        }}}}
+                    }}}}
+                    """,
+                    argname=argname)
+            else:
+                return self.format_code("""
                     {paramname} = (float) PyFloat_AsDouble({argname});
                     if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
                         goto exit;
                     }}}}
-                }}}}
-                """,
-                argname=argname)
+                    """,
+                    argname=argname)
         return super().parse_arg(argname, displayname, limited_capi=limited_capi)
 
 class double_converter(CConverter):
@@ -3890,19 +3899,28 @@ class double_converter(CConverter):
 
     def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
         if self.format_unit == 'd':
-            return self.format_code("""
-                if (PyFloat_CheckExact({argname})) {{{{
-                    {paramname} = PyFloat_AS_DOUBLE({argname});
-                }}}}
-                else
-                {{{{
+            if not limited_capi:
+                return self.format_code("""
+                    if (PyFloat_CheckExact({argname})) {{{{
+                        {paramname} = PyFloat_AS_DOUBLE({argname});
+                    }}}}
+                    else
+                    {{{{
+                        {paramname} = PyFloat_AsDouble({argname});
+                        if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
+                            goto exit;
+                        }}}}
+                    }}}}
+                    """,
+                    argname=argname)
+            else:
+                return self.format_code("""
                     {paramname} = PyFloat_AsDouble({argname});
                     if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
                         goto exit;
                     }}}}
-                }}}}
-                """,
-                argname=argname)
+                    """,
+                    argname=argname)
         return super().parse_arg(argname, displayname, limited_capi=limited_capi)