Skip to content

Commit ff3e9cd

Browse files
authored
gh-91320: Fix more old-style cast warnings in C++ (#92247)
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.
1 parent b270b82 commit ff3e9cd

File tree

3 files changed

+19
-16
lines changed

3 files changed

+19
-16
lines changed

Include/cpython/unicodeobject.h

+16-15
Original file line numberDiff line numberDiff line change
@@ -314,16 +314,15 @@ enum PyUnicode_Kind {
314314

315315
/* Return one of the PyUnicode_*_KIND values defined above. */
316316
#define PyUnicode_KIND(op) \
317-
(assert(PyUnicode_Check(op)), \
318-
assert(PyUnicode_IS_READY(op)), \
319-
((PyASCIIObject *)(op))->state.kind)
317+
(assert(PyUnicode_IS_READY(op)), \
318+
_PyASCIIObject_CAST(op)->state.kind)
320319

321320
/* Return a void pointer to the raw unicode buffer. */
322321
static inline void* _PyUnicode_COMPACT_DATA(PyObject *op) {
323322
if (PyUnicode_IS_ASCII(op)) {
324-
return (void*)(_PyASCIIObject_CAST(op) + 1);
323+
return _Py_STATIC_CAST(void*, (_PyASCIIObject_CAST(op) + 1));
325324
}
326-
return (void*)(_PyCompactUnicodeObject_CAST(op) + 1);
325+
return _Py_STATIC_CAST(void*, (_PyCompactUnicodeObject_CAST(op) + 1));
327326
}
328327

329328
static inline void* _PyUnicode_NONCOMPACT_DATA(PyObject *op) {
@@ -348,9 +347,9 @@ static inline void* PyUnicode_DATA(PyObject *op) {
348347
No checks are performed, use PyUnicode_KIND() before to ensure
349348
these will work correctly. */
350349

351-
#define PyUnicode_1BYTE_DATA(op) ((Py_UCS1*)PyUnicode_DATA(op))
352-
#define PyUnicode_2BYTE_DATA(op) ((Py_UCS2*)PyUnicode_DATA(op))
353-
#define PyUnicode_4BYTE_DATA(op) ((Py_UCS4*)PyUnicode_DATA(op))
350+
#define PyUnicode_1BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS1*, PyUnicode_DATA(op))
351+
#define PyUnicode_2BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS2*, PyUnicode_DATA(op))
352+
#define PyUnicode_4BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS4*, PyUnicode_DATA(op))
354353

355354
/* Returns the length of the unicode string. The caller has to make sure that
356355
the string has it's canonical representation set before calling
@@ -373,16 +372,16 @@ static inline void PyUnicode_WRITE(unsigned int kind, void *data,
373372
{
374373
if (kind == PyUnicode_1BYTE_KIND) {
375374
assert(value <= 0xffU);
376-
((Py_UCS1 *)data)[index] = (Py_UCS1)value;
375+
_Py_STATIC_CAST(Py_UCS1*, data)[index] = _Py_STATIC_CAST(Py_UCS1, value);
377376
}
378377
else if (kind == PyUnicode_2BYTE_KIND) {
379378
assert(value <= 0xffffU);
380-
((Py_UCS2 *)data)[index] = (Py_UCS2)value;
379+
_Py_STATIC_CAST(Py_UCS2*, data)[index] = _Py_STATIC_CAST(Py_UCS2, value);
381380
}
382381
else {
383382
assert(kind == PyUnicode_4BYTE_KIND);
384383
assert(value <= 0x10ffffU);
385-
((Py_UCS4 *)data)[index] = value;
384+
_Py_STATIC_CAST(Py_UCS4*, data)[index] = value;
386385
}
387386
}
388387
#define PyUnicode_WRITE(kind, data, index, value) \
@@ -394,13 +393,13 @@ static inline Py_UCS4 PyUnicode_READ(unsigned int kind,
394393
const void *data, Py_ssize_t index)
395394
{
396395
if (kind == PyUnicode_1BYTE_KIND) {
397-
return ((const Py_UCS1 *)data)[index];
396+
return _Py_STATIC_CAST(const Py_UCS1*, data)[index];
398397
}
399398
if (kind == PyUnicode_2BYTE_KIND) {
400-
return ((const Py_UCS2 *)data)[index];
399+
return _Py_STATIC_CAST(const Py_UCS2*, data)[index];
401400
}
402401
assert(kind == PyUnicode_4BYTE_KIND);
403-
return ((const Py_UCS4 *)data)[index];
402+
return _Py_STATIC_CAST(const Py_UCS4*, data)[index];
404403
}
405404
#define PyUnicode_READ(kind, data, index) \
406405
PyUnicode_READ((unsigned int)(kind), (const void*)(data), (index))
@@ -693,7 +692,9 @@ static inline const char* PyUnicode_AS_DATA(PyObject *op)
693692
{
694693
_Py_COMP_DIAG_PUSH
695694
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
696-
return (const char *)PyUnicode_AS_UNICODE(op);
695+
Py_UNICODE *data = PyUnicode_AS_UNICODE(op);
696+
// In C++, casting directly PyUnicode* to const char* is not valid
697+
return _Py_STATIC_CAST(const char*, _Py_STATIC_CAST(const void*, data));
697698
_Py_COMP_DIAG_POP
698699
}
699700
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000

Include/cpython/weakrefobject.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
3838

3939
static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) {
4040
assert(PyWeakref_Check(ref_obj));
41-
PyWeakReference *ref = (PyWeakReference *)ref_obj;
41+
PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj);
4242
PyObject *obj = ref->wr_object;
4343
// Explanation for the Py_REFCNT() check: when a weakref's target is part
4444
// of a long chain of deallocations which triggers the trashcan mechanism,

Lib/test/test_cppext.py

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
# a C++ extension using the Python C API does not emit C++ compiler
2828
# warnings
2929
'-Werror',
30+
# Warn on old-style cast (C cast) like: (PyObject*)op
31+
'-Wold-style-cast',
3032
]
3133
else:
3234
# Don't pass any compiler flag to MSVC

0 commit comments

Comments
 (0)