Skip to content

bpo-45476: Convert PyFloat_AS_DOUBLE() to static inline #28961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,17 @@ Porting to Python 3.11
header provides functions like ``printf()`` and ``fopen()``.
(Contributed by Victor Stinner in :issue:`45434`.)

* Convert the following macros to static inline functions to disallow using
them as l-value:

* :c:func:`PyByteArray_AS_STRING`
* :c:func:`PyBytes_AS_STRING`
* :c:func:`PyFloat_AS_DOUBLE`

Moreover, :c:func:`PyUnicode_AS_UNICODE` becomes an alias to
:c:func:`PyUnicode_AsUnicode`.
(Contributed by Victor Stinner in :issue:`45476`.)

Deprecated
----------

Expand Down
21 changes: 15 additions & 6 deletions Include/cpython/bytearrayobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ typedef struct {
Py_ssize_t ob_exports; /* How many buffer exports */
} PyByteArrayObject;

/* Macros, trading safety for speed */
#define PyByteArray_AS_STRING(self) \
(assert(PyByteArray_Check(self)), \
Py_SIZE(self) ? ((PyByteArrayObject *)(self))->ob_start : _PyByteArray_empty_string)
#define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)), Py_SIZE(self))

PyAPI_DATA(char) _PyByteArray_empty_string[];

// Static inline function, trading safety for speed
static inline char* _PyByteArray_AS_STRING(PyByteArrayObject *self) {
assert(PyByteArray_Check(self));
if (Py_SIZE(self)) {
return self->ob_start;
}
else {
return _PyByteArray_empty_string;
}
}
#define PyByteArray_AS_STRING(op) _PyByteArray_AS_STRING((PyByteArrayObject *)(op))

// Macro, trading safety for speed
#define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)), Py_SIZE(self))
13 changes: 9 additions & 4 deletions Include/cpython/bytesobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ PyAPI_FUNC(PyObject*) _PyBytes_FromHex(
PyAPI_FUNC(PyObject *) _PyBytes_DecodeEscape(const char *, Py_ssize_t,
const char *, const char **);

/* Macro, trading safety for speed */
#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \
(((PyBytesObject *)(op))->ob_sval))
#define PyBytes_GET_SIZE(op) (assert(PyBytes_Check(op)),Py_SIZE(op))
// Static inline function, trading safety for speed
static inline char* _PyBytes_AS_STRING(PyBytesObject *op) {
assert(PyBytes_Check(op));
return op->ob_sval;
}
#define PyBytes_AS_STRING(op) _PyBytes_AS_STRING((PyBytesObject *)(op))

// Macro, trading safety for speed
#define PyBytes_GET_SIZE(op) (assert(PyBytes_Check(op)), Py_SIZE(op))

/* _PyBytes_Join(sep, x) is like sep.join(x). sep must be PyBytesObject*,
x must be an iterable object. */
Expand Down
10 changes: 7 additions & 3 deletions Include/cpython/floatobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ typedef struct {
double ob_fval;
} PyFloatObject;

// Macro version of PyFloat_AsDouble() trading safety for speed.
// It doesn't check if op is a double object.
#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval)
// Static inline version of PyFloat_AsDouble() trading safety for speed.
// It only checks if op is a Python float object in debug mode.
static inline double _PyFloat_AS_DOUBLE(PyFloatObject *op) {
assert(PyFloat_Check(op));
return op->ob_fval;
}
#define PyFloat_AS_DOUBLE(op) _PyFloat_AS_DOUBLE((PyFloatObject *)(op))
11 changes: 2 additions & 9 deletions Include/cpython/unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,16 +254,9 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency(
#define PyUnicode_GET_DATA_SIZE(op) \
(PyUnicode_GET_SIZE(op) * Py_UNICODE_SIZE)

/* Alias for PyUnicode_AsUnicode(). This will create a wchar_t/Py_UNICODE
representation on demand. Using this macro is very inefficient now,
try to port your code to use the new PyUnicode_*BYTE_DATA() macros or
use PyUnicode_WRITE() and PyUnicode_READ(). */

/* Alias for PyUnicode_AsUnicode(). */
/* Py_DEPRECATED(3.3) */
#define PyUnicode_AS_UNICODE(op) \
(assert(PyUnicode_Check(op)), \
(((PyASCIIObject *)(op))->wstr) ? (((PyASCIIObject *)(op))->wstr) : \
PyUnicode_AsUnicode(_PyObject_CAST(op)))
#define PyUnicode_AS_UNICODE(op) PyUnicode_AsUnicode(_PyObject_CAST(op))

/* Py_DEPRECATED(3.3) */
#define PyUnicode_AS_DATA(op) \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Convert the following macros to static inline functions to disallow using
them as l-value:

* :c:func:`PyByteArray_AS_STRING`
* :c:func:`PyBytes_AS_STRING`
* :c:func:`PyFloat_AS_DOUBLE`

Moreover, :c:func:`PyUnicode_AS_UNICODE` becomes an alias to
:c:func:`PyUnicode_AsUnicode`. Patch by Victor Stinner.