From 83dc0f14d0d034088a45faa2327909f5701fc500 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 3 May 2022 20:18:31 +0200 Subject: [PATCH] gh-91320: Fix more old-style cast warnings in C++ Use _Py_CAST(), _Py_STATIC_CAST() and _PyASCIIObject_CAST() in static inline functions to fix C++ compiler warnings: "use of old-style cast" (clang -Wold-style-cast). test_cppext now builds the C++ test extension with -Wold-style-cast. --- Include/cpython/unicodeobject.h | 31 ++++++++++++++++--------------- Include/cpython/weakrefobject.h | 2 +- Lib/test/test_cppext.py | 2 ++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 47194ac7829fd7..96bfaaf4d2badd 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -314,16 +314,15 @@ enum PyUnicode_Kind { /* Return one of the PyUnicode_*_KIND values defined above. */ #define PyUnicode_KIND(op) \ - (assert(PyUnicode_Check(op)), \ - assert(PyUnicode_IS_READY(op)), \ - ((PyASCIIObject *)(op))->state.kind) + (assert(PyUnicode_IS_READY(op)), \ + _PyASCIIObject_CAST(op)->state.kind) /* Return a void pointer to the raw unicode buffer. */ static inline void* _PyUnicode_COMPACT_DATA(PyObject *op) { if (PyUnicode_IS_ASCII(op)) { - return (void*)(_PyASCIIObject_CAST(op) + 1); + return _Py_STATIC_CAST(void*, (_PyASCIIObject_CAST(op) + 1)); } - return (void*)(_PyCompactUnicodeObject_CAST(op) + 1); + return _Py_STATIC_CAST(void*, (_PyCompactUnicodeObject_CAST(op) + 1)); } static inline void* _PyUnicode_NONCOMPACT_DATA(PyObject *op) { @@ -348,9 +347,9 @@ static inline void* PyUnicode_DATA(PyObject *op) { No checks are performed, use PyUnicode_KIND() before to ensure these will work correctly. */ -#define PyUnicode_1BYTE_DATA(op) ((Py_UCS1*)PyUnicode_DATA(op)) -#define PyUnicode_2BYTE_DATA(op) ((Py_UCS2*)PyUnicode_DATA(op)) -#define PyUnicode_4BYTE_DATA(op) ((Py_UCS4*)PyUnicode_DATA(op)) +#define PyUnicode_1BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS1*, PyUnicode_DATA(op)) +#define PyUnicode_2BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS2*, PyUnicode_DATA(op)) +#define PyUnicode_4BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS4*, PyUnicode_DATA(op)) /* Returns the length of the unicode string. The caller has to make sure that the string has it's canonical representation set before calling @@ -373,16 +372,16 @@ static inline void PyUnicode_WRITE(unsigned int kind, void *data, { if (kind == PyUnicode_1BYTE_KIND) { assert(value <= 0xffU); - ((Py_UCS1 *)data)[index] = (Py_UCS1)value; + _Py_STATIC_CAST(Py_UCS1*, data)[index] = _Py_STATIC_CAST(Py_UCS1, value); } else if (kind == PyUnicode_2BYTE_KIND) { assert(value <= 0xffffU); - ((Py_UCS2 *)data)[index] = (Py_UCS2)value; + _Py_STATIC_CAST(Py_UCS2*, data)[index] = _Py_STATIC_CAST(Py_UCS2, value); } else { assert(kind == PyUnicode_4BYTE_KIND); assert(value <= 0x10ffffU); - ((Py_UCS4 *)data)[index] = value; + _Py_STATIC_CAST(Py_UCS4*, data)[index] = value; } } #define PyUnicode_WRITE(kind, data, index, value) \ @@ -394,13 +393,13 @@ static inline Py_UCS4 PyUnicode_READ(unsigned int kind, const void *data, Py_ssize_t index) { if (kind == PyUnicode_1BYTE_KIND) { - return ((const Py_UCS1 *)data)[index]; + return _Py_STATIC_CAST(const Py_UCS1*, data)[index]; } if (kind == PyUnicode_2BYTE_KIND) { - return ((const Py_UCS2 *)data)[index]; + return _Py_STATIC_CAST(const Py_UCS2*, data)[index]; } assert(kind == PyUnicode_4BYTE_KIND); - return ((const Py_UCS4 *)data)[index]; + return _Py_STATIC_CAST(const Py_UCS4*, data)[index]; } #define PyUnicode_READ(kind, data, index) \ PyUnicode_READ((unsigned int)(kind), (const void*)(data), (index)) @@ -693,7 +692,9 @@ static inline const char* PyUnicode_AS_DATA(PyObject *op) { _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS - return (const char *)PyUnicode_AS_UNICODE(op); + Py_UNICODE *data = PyUnicode_AS_UNICODE(op); + // In C++, casting directly PyUnicode* to const char* is not valid + return _Py_STATIC_CAST(const char*, _Py_STATIC_CAST(const void*, data)); _Py_COMP_DIAG_POP } #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 diff --git a/Include/cpython/weakrefobject.h b/Include/cpython/weakrefobject.h index 1078fffc2e0a5f..bec69ba90d6b98 100644 --- a/Include/cpython/weakrefobject.h +++ b/Include/cpython/weakrefobject.h @@ -38,7 +38,7 @@ PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) { assert(PyWeakref_Check(ref_obj)); - PyWeakReference *ref = (PyWeakReference *)ref_obj; + PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj); PyObject *obj = ref->wr_object; // Explanation for the Py_REFCNT() check: when a weakref's target is part // of a long chain of deallocations which triggers the trashcan mechanism, diff --git a/Lib/test/test_cppext.py b/Lib/test/test_cppext.py index 99f6062d79d478..fbb79bb8ac3ed1 100644 --- a/Lib/test/test_cppext.py +++ b/Lib/test/test_cppext.py @@ -27,6 +27,8 @@ # a C++ extension using the Python C API does not emit C++ compiler # warnings '-Werror', + # Warn on old-style cast (C cast) like: (PyObject*)op + '-Wold-style-cast', ] else: # Don't pass any compiler flag to MSVC