Skip to content
Open
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
74 changes: 70 additions & 4 deletions Doc/c-api/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -526,14 +526,26 @@ to the C language.
Outdated macros
---------------

The following macros have been used to features that have been standardized
in C11.
The following :term:`soft deprecated` macros have been used to features that
have been standardized in C11 (or previous standards).

.. c:macro:: Py_ALIGNED(num)
Specify alignment to *num* bytes on compilers that support it.
On some GCC-like compilers, specify alignment to *num* bytes.
This does nothing on other compilers.

Consider using the C11 standard ``_Alignas`` specifier over this macro.
Use the standard ``alignas`` specifier rather than this macro.

.. deprecated:: next
The macro is :term:`soft deprecated`.

.. c:macro:: PY_FORMAT_SIZE_T
The :c:func:`printf` formatting modifier for :c:type:`size_t`.
Use ``"z"`` directly instead.

.. deprecated:: next
The macro is :term:`soft deprecated`.

.. c:macro:: Py_LL(number)
Py_ULL(number)
Expand All @@ -546,6 +558,38 @@ in C11.
Consider using the C99 standard suffixes ``LL`` and ``LLU`` directly.
.. deprecated:: next
The macro is :term:`soft deprecated`.
.. c:macro:: PY_LONG_LONG
PY_INT32_T
PY_UINT32_T
PY_INT64_T
PY_UINT64_T
Aliases for the types :c:type:`!long long`, :c:type:`!int32_t`,
:c:type:`!uint32_t`. :c:type:`!int64_t` and :c:type:`!uint64_t`,
respectively.
Historically, these types needed compiler-specific extensions.
.. deprecated:: next
These macros are :term:`soft deprecated`.
.. c:macro:: PY_LLONG_MIN
PY_LLONG_MAX
PY_ULLONG_MAX
PY_SIZE_MAX
Aliases for the values :c:macro:`!LLONG_MIN`, :c:macro:`!LLONG_MAX`,
:c:macro:`!ULLONG_MAX`, and :c:macro:`!SIZE_MAX`, respectively.
Use these standard names instead.
The required header, ``<limits.h>``,
:ref:`is included <capi-system-includes>` in ``Python.h``.
.. deprecated:: next
These macros are :term:`soft deprecated`.
.. c:macro:: Py_MEMCPY(dest, src, n)
This is a :term:`soft deprecated` alias to :c:func:`!memcpy`.
Expand All @@ -554,6 +598,25 @@ in C11.
.. deprecated:: 3.14
The macro is :term:`soft deprecated`.
.. c:macro:: Py_UNICODE_SIZE
Size of the :c:type:`!wchar_t` type.
Use ``sizeof(wchar_t)`` or ``WCHAR_WIDTH/8`` instead.
The required header for the latter, ``<limits.h>``,
:ref:`is included <capi-system-includes>` in ``Python.h``.
.. deprecated:: next
The macro is :term:`soft deprecated`.
.. c:macro:: Py_UNICODE_WIDE
Defined if ``wchar_t`` can hold a Unicode character (UCS-4).
Use ``sizeof(wchar_t) >= 4`` instead
.. deprecated:: next
The macro is :term:`soft deprecated`.
.. c:macro:: Py_VA_COPY
This is a :term:`soft deprecated` alias to the C99-standard ``va_copy``
Expand All @@ -564,6 +627,9 @@ in C11.
.. versionchanged:: 3.6
This is now an alias to ``va_copy``.
.. deprecated:: next
The macro is :term:`soft deprecated`.
.. _api-objects:
Expand Down
2 changes: 0 additions & 2 deletions Doc/deprecations/c-api-pending-removal-in-3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ Pending removal in Python 3.15
Use :c:func:`PyWeakref_GetRef` instead. The `pythoncapi-compat project
<https://github.com/python/pythoncapi-compat/>`__ can be used to get
:c:func:`PyWeakref_GetRef` on Python 3.12 and older.
* :c:type:`Py_UNICODE` type and the :c:macro:`!Py_UNICODE_WIDE` macro:
Use :c:type:`wchar_t` instead.
* :c:func:`!PyUnicode_AsDecodedObject`:
Use :c:func:`PyCodec_Decode` instead.
* :c:func:`!PyUnicode_AsDecodedUnicode`:
Expand Down
18 changes: 18 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1864,6 +1864,24 @@ Deprecated C APIs
use the C11 standard ``<math.h>`` :c:macro:`!INFINITY` instead.
(Contributed by Sergey B Kirpichev in :gh:`141004`.)

* The following macros are :term:`soft deprecated`:

- :c:macro:`Py_ALIGNED`: Prefer ``alignas`` instead.
- :c:macro:`PY_FORMAT_SIZE_T`: Use ``"z"`` directly.
- :c:macro:`Py_LL` & :c:macro:`Py_ULL`:
Use standard suffixes, ``LL`` & ``ULL``.
- :c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`,
:c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`,
:c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`:
Use C99 types/limits.
- :c:macro:`Py_UNICODE_SIZE`: Use ``sizeof(wchar_t)`` directly.
- :c:macro:`Py_VA_COPY`: Use ``va_copy`` directly.

The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal,
is :term:`soft deprecated` instead.

(Contributed by Petr Viktorin in :gh:`146175`.)

* :c:macro:`!Py_MATH_El` and :c:macro:`!Py_MATH_PIl` are deprecated
since 3.15 and will be removed in 3.20.
(Contributed by Sergey B Kirpichev in :gh:`141004`.)
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
new_refcnt = _Py_IMMORTAL_INITIAL_REFCNT;
}
# if SIZEOF_VOID_P > 4
op->ob_refcnt = (PY_UINT32_T)new_refcnt;
op->ob_refcnt = (uint32_t)new_refcnt;
# else
op->ob_refcnt = new_refcnt;
# endif
Expand Down
2 changes: 1 addition & 1 deletion Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ whose size is determined when the object is allocated.
struct _object {
_Py_ANONYMOUS union {
#if SIZEOF_VOID_P > 4
PY_INT64_T ob_refcnt_full; /* This field is needed for efficient initialization with Clang on ARM */
int64_t ob_refcnt_full; /* This field is needed for efficient initialization with Clang on ARM */
struct {
# if PY_BIG_ENDIAN
uint16_t ob_flags;
Expand Down
4 changes: 3 additions & 1 deletion Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,9 @@ extern "C" {
/*
* Specify alignment on compilers that support it.
*/
#if defined(__GNUC__) && __GNUC__ >= 3
#ifdef Py_BUILD_CORE
// always use _Py_ALIGNED_DEF instead
#elif defined(__GNUC__) && __GNUC__ >= 3
#define Py_ALIGNED(x) __attribute__((aligned(x)))
#else
#define Py_ALIGNED(x)
Expand Down
8 changes: 4 additions & 4 deletions Include/refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
return (_Py_atomic_load_uint32_relaxed(&op->ob_ref_local) ==
_Py_IMMORTAL_REFCNT_LOCAL);
#elif SIZEOF_VOID_P > 4
return _Py_CAST(PY_INT32_T, op->ob_refcnt) < 0;
return _Py_CAST(int32_t, op->ob_refcnt) < 0;
#else
return op->ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT;
#endif
Expand Down Expand Up @@ -164,7 +164,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
}
#ifndef Py_GIL_DISABLED
#if SIZEOF_VOID_P > 4
ob->ob_refcnt = (PY_UINT32_T)refcnt;
ob->ob_refcnt = (uint32_t)refcnt;
#else
ob->ob_refcnt = refcnt;
#endif
Expand Down Expand Up @@ -278,7 +278,7 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
_Py_atomic_add_ssize(&op->ob_ref_shared, (1 << _Py_REF_SHARED_SHIFT));
}
#elif SIZEOF_VOID_P > 4
PY_UINT32_T cur_refcnt = op->ob_refcnt;
uint32_t cur_refcnt = op->ob_refcnt;
if (cur_refcnt >= _Py_IMMORTAL_INITIAL_REFCNT) {
// the object is immortal
_Py_INCREF_IMMORTAL_STAT_INC();
Expand Down Expand Up @@ -387,7 +387,7 @@ static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
#if SIZEOF_VOID_P > 4
/* If an object has been freed, it will have a negative full refcnt
* If it has not it been freed, will have a very large refcnt */
if (op->ob_refcnt_full <= 0 || op->ob_refcnt > (((PY_UINT32_T)-1) - (1<<20))) {
if (op->ob_refcnt_full <= 0 || op->ob_refcnt > (((uint32_t)-1) - (1<<20))) {
#else
if (op->ob_refcnt <= 0) {
#endif
Expand Down
8 changes: 2 additions & 6 deletions Include/unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,9 @@ Copyright (c) Corporation for National Research Initiatives.
#error Must define SIZEOF_WCHAR_T
#endif

/* Soft-deprecated defines */
#define Py_UNICODE_SIZE SIZEOF_WCHAR_T

/* If wchar_t can be used for UCS-4 storage, set Py_UNICODE_WIDE.
Otherwise, Unicode strings are stored as UCS-2 (with limited support
for UTF-16) */

#if Py_UNICODE_SIZE >= 4
#if SIZEOF_WCHAR_T >= 4
#define Py_UNICODE_WIDE
#endif

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
The following macros are :term:`soft deprecated`:
:c:macro:`Py_ALIGNED`,
:c:macro:`PY_FORMAT_SIZE_T`,
:c:macro:`Py_LL`, :c:macro:`Py_ULL`,
:c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`,
:c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`,
:c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`,
:c:macro:`Py_UNICODE_SIZE`,
:c:macro:`Py_VA_COPY`.

The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, is
:term:`soft deprecated` instead.
2 changes: 1 addition & 1 deletion Modules/_io/stringio.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ resize_buffer(stringio *self, size_t size)
alloc = size + 1;
}

if (alloc > PY_SIZE_MAX / sizeof(Py_UCS4))
if (alloc > SIZE_MAX / sizeof(Py_UCS4))
goto overflow;
new_buf = (Py_UCS4 *)PyMem_Realloc(self->buf, alloc * sizeof(Py_UCS4));
if (new_buf == NULL) {
Expand Down
35 changes: 35 additions & 0 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2607,6 +2607,40 @@ create_managed_weakref_nogc_type(PyObject *self, PyObject *Py_UNUSED(args))
}


static PyObject*
test_soft_deprecated_macros(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
test_soft_deprecated_macros(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
test_soft_deprecated_macros(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
{

// Test soft-deprecated macros
Py_ALIGNED(64) char buf[4];
#ifdef __GNUC__
// Py_ALIGNED must compile everywhere, but only does something
// on "supported" compilers, i.e. GCC
Py_BUILD_ASSERT(__extension__ __alignof__(buf) >= 64);
#endif
assert(strcmp(PY_FORMAT_SIZE_T, "z") == 0);
Py_BUILD_ASSERT(Py_LL(123) == 123LL);
Py_BUILD_ASSERT(sizeof(Py_LL(123)) == sizeof(long long));
Py_BUILD_ASSERT(sizeof(Py_ULL(123)) == sizeof(unsigned long long));
Py_BUILD_ASSERT(sizeof(PY_LONG_LONG) == sizeof(long long));
Py_BUILD_ASSERT(sizeof(PY_INT32_T) == sizeof(int32_t));
Py_BUILD_ASSERT(sizeof(PY_UINT32_T) == sizeof(uint32_t));
Py_BUILD_ASSERT(sizeof(PY_INT64_T) == sizeof(int64_t));
Py_BUILD_ASSERT(sizeof(PY_UINT64_T) == sizeof(uint64_t));
Py_BUILD_ASSERT(PY_LLONG_MIN == LLONG_MIN);
Py_BUILD_ASSERT(PY_LLONG_MAX == LLONG_MAX);
Py_BUILD_ASSERT(PY_ULLONG_MAX == ULLONG_MAX);
Py_BUILD_ASSERT(PY_SIZE_MAX == SIZE_MAX);
Py_BUILD_ASSERT(PY_LLONG_MIN == LLONG_MIN);
Py_MEMCPY(buf, "abc", 4);
assert(strcmp(buf, "abc") == 0);
Py_BUILD_ASSERT(Py_UNICODE_SIZE == sizeof(wchar_t));
#ifdef Py_UNICODE_WIDE
Py_BUILD_ASSERT(sizeof(wchar_t) >= 4);
#else
Py_BUILD_ASSERT(sizeof(wchar_t) < 4);
#endif
Py_RETURN_NONE;
}

static PyMethodDef TestMethods[] = {
{"set_errno", set_errno, METH_VARARGS},
{"test_config", test_config, METH_NOARGS},
Expand Down Expand Up @@ -2704,6 +2738,7 @@ static PyMethodDef TestMethods[] = {
{"toggle_reftrace_printer", toggle_reftrace_printer, METH_O},
{"create_managed_weakref_nogc_type",
create_managed_weakref_nogc_type, METH_NOARGS},
{"test_soft_deprecated_macros", test_soft_deprecated_macros, METH_NOARGS},
{NULL, NULL} /* sentinel */
};

Expand Down
4 changes: 1 addition & 3 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2760,11 +2760,9 @@ array_buffer_getbuf(PyObject *op, Py_buffer *view, int flags)
view->internal = NULL;
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
view->format = (char *)self->ob_descr->formats;
#ifdef Py_UNICODE_WIDE
if (self->ob_descr->typecode == 'u') {
if (sizeof(wchar_t) >= 4 && self->ob_descr->typecode == 'u') {
view->format = "w";
}
#endif
}

self->ob_exports++;
Expand Down
12 changes: 6 additions & 6 deletions Modules/binascii.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ get_binascii_state(PyObject *module)


/* Align to 64 bytes for L1 cache line friendliness */
static const unsigned char table_a2b_base64[] Py_ALIGNED(64) = {
static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base64[] = {
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
Expand Down Expand Up @@ -110,7 +110,7 @@ static const unsigned char table_a2b_base64[] Py_ALIGNED(64) = {
*/

/* Align to 64 bytes for L1 cache line friendliness */
static const unsigned char table_b2a_base64[] Py_ALIGNED(64) =
static const _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/* Encode 3 bytes into 4 base64 characters. */
Expand Down Expand Up @@ -189,7 +189,7 @@ base64_decode_fast(const unsigned char *in, Py_ssize_t in_len,
}


static const unsigned char table_a2b_base85[] Py_ALIGNED(64) = {
static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base85[] = {
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,62,-1,63, 64,65,66,-1, 67,68,69,70, -1,71,-1,-1,
Expand All @@ -209,7 +209,7 @@ static const unsigned char table_a2b_base85[] Py_ALIGNED(64) = {
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
};

static const unsigned char table_a2b_base85_a85[] Py_ALIGNED(64) = {
static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base85_a85[] = {
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
Expand All @@ -229,11 +229,11 @@ static const unsigned char table_a2b_base85_a85[] Py_ALIGNED(64) = {
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
};

static const unsigned char table_b2a_base85[] Py_ALIGNED(64) =
static const _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base85[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";

static const unsigned char table_b2a_base85_a85[] Py_ALIGNED(64) =
static const _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base85_a85[] =
"!\"#$%&\'()*+,-./0123456789:;<=>?@" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu";

Expand Down
2 changes: 1 addition & 1 deletion Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6261,7 +6261,7 @@ socket_gethostbyaddr(PyObject *self, PyObject *args)
gethostbyaddr_r is 8-byte aligned, which at least llvm-gcc
does not ensure. The attribute below instructs the compiler
to maintain this alignment. */
char buf[16384] Py_ALIGNED(8);
_Py_ALIGNED_DEF(8, char) buf[16384];
int buf_len = (sizeof buf) - 1;
int errnop;
#endif
Expand Down
5 changes: 2 additions & 3 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5580,15 +5580,14 @@ _Py_EncodeUTF8Ex(const wchar_t *text, char **str, size_t *error_pos,
Py_ssize_t ch_pos = i;
Py_UCS4 ch = text[i];
i++;
#if Py_UNICODE_SIZE == 2
if (Py_UNICODE_IS_HIGH_SURROGATE(ch)
if (sizeof(wchar_t) == 2
&& Py_UNICODE_IS_HIGH_SURROGATE(ch)
&& i < len
&& Py_UNICODE_IS_LOW_SURROGATE(text[i]))
{
ch = Py_UNICODE_JOIN_SURROGATES(ch, text[i]);
i++;
}
#endif

if (ch < 0x80) {
/* Encode ASCII */
Expand Down
Loading
Loading