diff options
author | Victor Stinner <vstinner@python.org> | 2022-03-31 07:59:27 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-31 07:59:27 (GMT) |
commit | c14d7e4b816134b8e93ece4066a86d229631ce96 (patch) | |
tree | 6b2ac5b9c3e502d77d1ff05bdcc88e918dba1ad4 | |
parent | db4dada5108dd49ebca23e4559a53630a2df8447 (diff) | |
download | cpython-c14d7e4b816134b8e93ece4066a86d229631ce96.zip cpython-c14d7e4b816134b8e93ece4066a86d229631ce96.tar.gz cpython-c14d7e4b816134b8e93ece4066a86d229631ce96.tar.bz2 |
bpo-47164: Add _PyASCIIObject_CAST() macro (GH-32191)
Add macros to cast objects to PyASCIIObject*, PyCompactUnicodeObject*
and PyUnicodeObject*: _PyASCIIObject_CAST(),
_PyCompactUnicodeObject_CAST() and _PyUnicodeObject_CAST(). Using
these new macros make the code more readable and check their argument
with: assert(PyUnicode_Check(op)).
Remove redundant assert(PyUnicode_Check(op)) in macros using directly
or indirectly these new CAST macros.
Replacing existing casts with these macros.
-rw-r--r-- | Include/cpython/unicodeobject.h | 67 | ||||
-rw-r--r-- | Include/unicodeobject.h | 2 | ||||
-rw-r--r-- | Modules/_collectionsmodule.c | 2 | ||||
-rw-r--r-- | Objects/dictobject.c | 2 | ||||
-rw-r--r-- | Objects/setobject.c | 6 | ||||
-rw-r--r-- | Objects/typeobject.c | 6 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 57 | ||||
-rw-r--r-- | Python/traceback.c | 12 |
8 files changed, 76 insertions, 78 deletions
diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 77a171b..69e4abf 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -234,6 +234,15 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( PyObject *op, int check_content); + +#define _PyASCIIObject_CAST(op) \ + (assert(PyUnicode_Check(op)), (PyASCIIObject*)(op)) +#define _PyCompactUnicodeObject_CAST(op) \ + (assert(PyUnicode_Check(op)), (PyCompactUnicodeObject*)(op)) +#define _PyUnicodeObject_CAST(op) \ + (assert(PyUnicode_Check(op)), (PyUnicodeObject*)(op)) + + /* Fast access macros */ /* Returns the deprecated Py_UNICODE representation's size in code units @@ -243,11 +252,10 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( /* Py_DEPRECATED(3.3) */ #define PyUnicode_GET_SIZE(op) \ - (assert(PyUnicode_Check(op)), \ - (((PyASCIIObject *)(op))->wstr) ? \ + (_PyASCIIObject_CAST(op)->wstr ? \ PyUnicode_WSTR_LENGTH(op) : \ ((void)PyUnicode_AsUnicode(_PyObject_CAST(op)),\ - assert(((PyASCIIObject *)(op))->wstr), \ + assert(_PyASCIIObject_CAST(op)->wstr), \ PyUnicode_WSTR_LENGTH(op))) /* Py_DEPRECATED(3.3) */ @@ -261,9 +269,8 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( /* Py_DEPRECATED(3.3) */ #define PyUnicode_AS_UNICODE(op) \ - (assert(PyUnicode_Check(op)), \ - (((PyASCIIObject *)(op))->wstr) ? (((PyASCIIObject *)(op))->wstr) : \ - PyUnicode_AsUnicode(_PyObject_CAST(op))) + (_PyASCIIObject_CAST(op)->wstr ? _PyASCIIObject_CAST(op)->wstr : \ + PyUnicode_AsUnicode(_PyObject_CAST(op))) /* Py_DEPRECATED(3.3) */ #define PyUnicode_AS_DATA(op) \ @@ -281,25 +288,24 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( /* Use only if you know it's a string */ #define PyUnicode_CHECK_INTERNED(op) \ - (((PyASCIIObject *)(op))->state.interned) + (_PyASCIIObject_CAST(op)->state.interned) /* Return true if the string contains only ASCII characters, or 0 if not. The string may be compact (PyUnicode_IS_COMPACT_ASCII) or not, but must be ready. */ #define PyUnicode_IS_ASCII(op) \ - (assert(PyUnicode_Check(op)), \ - assert(PyUnicode_IS_READY(op)), \ - ((PyASCIIObject*)op)->state.ascii) + (assert(PyUnicode_IS_READY(op)), \ + _PyASCIIObject_CAST(op)->state.ascii) /* Return true if the string is compact or 0 if not. No type checks or Ready calls are performed. */ #define PyUnicode_IS_COMPACT(op) \ - (((PyASCIIObject*)(op))->state.compact) + (_PyASCIIObject_CAST(op)->state.compact) /* Return true if the string is a compact ASCII string (use PyASCIIObject structure), or 0 if not. No type checks or Ready calls are performed. */ #define PyUnicode_IS_COMPACT_ASCII(op) \ - (((PyASCIIObject*)op)->state.ascii && PyUnicode_IS_COMPACT(op)) + (_PyASCIIObject_CAST(op)->state.ascii && PyUnicode_IS_COMPACT(op)) enum PyUnicode_Kind { /* String contains only wstr byte characters. This is only possible @@ -323,23 +329,21 @@ 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. */ #define _PyUnicode_COMPACT_DATA(op) \ - (PyUnicode_IS_ASCII(op) ? \ - ((void*)((PyASCIIObject*)(op) + 1)) : \ - ((void*)((PyCompactUnicodeObject*)(op) + 1))) + (PyUnicode_IS_ASCII(op) ? \ + ((void*)(_PyASCIIObject_CAST(op) + 1)) : \ + ((void*)(_PyCompactUnicodeObject_CAST(op) + 1))) #define _PyUnicode_NONCOMPACT_DATA(op) \ - (assert(((PyUnicodeObject*)(op))->data.any), \ - ((((PyUnicodeObject *)(op))->data.any))) + (assert(_PyUnicodeObject_CAST(op)->data.any), \ + (_PyUnicodeObject_CAST(op)->data.any)) #define PyUnicode_DATA(op) \ - (assert(PyUnicode_Check(op)), \ - PyUnicode_IS_COMPACT(op) ? _PyUnicode_COMPACT_DATA(op) : \ + (PyUnicode_IS_COMPACT(op) ? _PyUnicode_COMPACT_DATA(op) : \ _PyUnicode_NONCOMPACT_DATA(op)) /* In the access macros below, "kind" may be evaluated more than once. @@ -386,8 +390,7 @@ enum PyUnicode_Kind { PyUnicode_READ_CHAR, for multiple consecutive reads callers should cache kind and use PyUnicode_READ instead. */ #define PyUnicode_READ_CHAR(unicode, index) \ - (assert(PyUnicode_Check(unicode)), \ - assert(PyUnicode_IS_READY(unicode)), \ + (assert(PyUnicode_IS_READY(unicode)), \ (Py_UCS4) \ (PyUnicode_KIND((unicode)) == PyUnicode_1BYTE_KIND ? \ ((const Py_UCS1 *)(PyUnicode_DATA((unicode))))[(index)] : \ @@ -401,23 +404,21 @@ enum PyUnicode_Kind { the string has it's canonical representation set before calling this macro. Call PyUnicode_(FAST_)Ready to ensure that. */ #define PyUnicode_GET_LENGTH(op) \ - (assert(PyUnicode_Check(op)), \ - assert(PyUnicode_IS_READY(op)), \ - ((PyASCIIObject *)(op))->length) + (assert(PyUnicode_IS_READY(op)), \ + _PyASCIIObject_CAST(op)->length) /* Fast check to determine whether an object is ready. Equivalent to - PyUnicode_IS_COMPACT(op) || ((PyUnicodeObject*)(op))->data.any */ + PyUnicode_IS_COMPACT(op) || _PyUnicodeObject_CAST(op)->data.any */ -#define PyUnicode_IS_READY(op) (((PyASCIIObject*)op)->state.ready) +#define PyUnicode_IS_READY(op) (_PyASCIIObject_CAST(op)->state.ready) /* PyUnicode_READY() does less work than _PyUnicode_Ready() in the best case. If the canonical representation is not yet set, it will still call _PyUnicode_Ready(). Returns 0 on success and -1 on errors. */ #define PyUnicode_READY(op) \ - (assert(PyUnicode_Check(op)), \ - (PyUnicode_IS_READY(op) ? \ + ((PyUnicode_IS_READY(op) ? \ 0 : _PyUnicode_Ready(_PyObject_CAST(op)))) /* Return a maximum character value which is suitable for creating another @@ -436,8 +437,8 @@ enum PyUnicode_Kind { Py_DEPRECATED(3.3) static inline Py_ssize_t PyUnicode_WSTR_LENGTH(PyObject *op) { return PyUnicode_IS_COMPACT_ASCII(op) ? - ((PyASCIIObject*)op)->length : - ((PyCompactUnicodeObject*)op)->wstr_length; + _PyASCIIObject_CAST(op)->length : + _PyCompactUnicodeObject_CAST(op)->wstr_length; } #define PyUnicode_WSTR_LENGTH(op) PyUnicode_WSTR_LENGTH(_PyObject_CAST(op)) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 6426c5d..1d2f546 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -112,7 +112,7 @@ PyAPI_DATA(PyTypeObject) PyUnicode_Type; PyAPI_DATA(PyTypeObject) PyUnicodeIter_Type; #define PyUnicode_Check(op) \ - PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) #define PyUnicode_CheckExact(op) Py_IS_TYPE(op, &PyUnicode_Type) /* --- Constants ---------------------------------------------------------- */ diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index e7bd8bc..b47f977 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2352,7 +2352,7 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping, break; if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) + (hash = _PyASCIIObject_CAST(key)->hash) == -1) { hash = PyObject_Hash(key); if (hash == -1) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 635a738..88addfd 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -286,7 +286,7 @@ static inline Py_hash_t unicode_get_hash(PyObject *o) { assert(PyUnicode_CheckExact(o)); - return ((PyASCIIObject*)o)->hash; + return _PyASCIIObject_CAST(o)->hash; } /* Print summary info about the state of the optimized allocator */ diff --git a/Objects/setobject.c b/Objects/setobject.c index c65b7d5..022ae8e 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -346,7 +346,7 @@ set_add_key(PySetObject *so, PyObject *key) Py_hash_t hash; if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { + (hash = _PyASCIIObject_CAST(key)->hash) == -1) { hash = PyObject_Hash(key); if (hash == -1) return -1; @@ -360,7 +360,7 @@ set_contains_key(PySetObject *so, PyObject *key) Py_hash_t hash; if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { + (hash = _PyASCIIObject_CAST(key)->hash) == -1) { hash = PyObject_Hash(key); if (hash == -1) return -1; @@ -374,7 +374,7 @@ set_discard_key(PySetObject *so, PyObject *key) Py_hash_t hash; if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { + (hash = _PyASCIIObject_CAST(key)->hash) == -1) { hash = PyObject_Hash(key); if (hash == -1) return -1; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 4bed3ef..5de8c3d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3759,7 +3759,7 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) { Py_hash_t hash; if (!PyUnicode_CheckExact(name) || - (hash = ((PyASCIIObject *) name)->hash) == -1) + (hash = _PyASCIIObject_CAST(name)->hash) == -1) { hash = PyObject_Hash(name); if (hash == -1) { @@ -3853,7 +3853,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) struct type_cache_entry *entry = &cache->hashtable[h]; entry->version = type->tp_version_tag; entry->value = res; /* borrowed */ - assert(((PyASCIIObject *)(name))->hash != -1); + assert(_PyASCIIObject_CAST(name)->hash != -1); #if MCACHE_STATS if (entry->name != Py_None && entry->name != name) { cache->collisions++; @@ -8951,7 +8951,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co, if (cframe->f_lasti >= 0) { // MAKE_CELL and COPY_FREE_VARS have no quickened forms, so no need // to use _PyOpcode_Deopt here: - assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL || + assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL || _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS); assert(PyCell_Check(firstarg)); firstarg = PyCell_GET(firstarg); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 72f9245..5a1d2c0 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -113,46 +113,46 @@ extern "C" { #endif #define _PyUnicode_UTF8(op) \ - (((PyCompactUnicodeObject*)(op))->utf8) + (_PyCompactUnicodeObject_CAST(op)->utf8) #define PyUnicode_UTF8(op) \ (assert(_PyUnicode_CHECK(op)), \ assert(PyUnicode_IS_READY(op)), \ PyUnicode_IS_COMPACT_ASCII(op) ? \ - ((char*)((PyASCIIObject*)(op) + 1)) : \ + ((char*)(_PyASCIIObject_CAST(op) + 1)) : \ _PyUnicode_UTF8(op)) #define _PyUnicode_UTF8_LENGTH(op) \ - (((PyCompactUnicodeObject*)(op))->utf8_length) + (_PyCompactUnicodeObject_CAST(op)->utf8_length) #define PyUnicode_UTF8_LENGTH(op) \ (assert(_PyUnicode_CHECK(op)), \ assert(PyUnicode_IS_READY(op)), \ PyUnicode_IS_COMPACT_ASCII(op) ? \ - ((PyASCIIObject*)(op))->length : \ + _PyASCIIObject_CAST(op)->length : \ _PyUnicode_UTF8_LENGTH(op)) #define _PyUnicode_WSTR(op) \ - (((PyASCIIObject*)(op))->wstr) + (_PyASCIIObject_CAST(op)->wstr) /* Don't use deprecated macro of unicodeobject.h */ #undef PyUnicode_WSTR_LENGTH #define PyUnicode_WSTR_LENGTH(op) \ - (PyUnicode_IS_COMPACT_ASCII(op) ? \ - ((PyASCIIObject*)op)->length : \ - ((PyCompactUnicodeObject*)op)->wstr_length) + (PyUnicode_IS_COMPACT_ASCII(op) ? \ + _PyASCIIObject_CAST(op)->length : \ + _PyCompactUnicodeObject_CAST(op)->wstr_length) #define _PyUnicode_WSTR_LENGTH(op) \ - (((PyCompactUnicodeObject*)(op))->wstr_length) + (_PyCompactUnicodeObject_CAST(op)->wstr_length) #define _PyUnicode_LENGTH(op) \ - (((PyASCIIObject *)(op))->length) + (_PyASCIIObject_CAST(op)->length) #define _PyUnicode_STATE(op) \ - (((PyASCIIObject *)(op))->state) + (_PyASCIIObject_CAST(op)->state) #define _PyUnicode_HASH(op) \ - (((PyASCIIObject *)(op))->hash) + (_PyASCIIObject_CAST(op)->hash) #define _PyUnicode_KIND(op) \ (assert(_PyUnicode_CHECK(op)), \ - ((PyASCIIObject *)(op))->state.kind) + _PyASCIIObject_CAST(op)->state.kind) #define _PyUnicode_GET_LENGTH(op) \ (assert(_PyUnicode_CHECK(op)), \ - ((PyASCIIObject *)(op))->length) + _PyASCIIObject_CAST(op)->length) #define _PyUnicode_DATA_ANY(op) \ - (((PyUnicodeObject*)(op))->data.any) + (_PyUnicodeObject_CAST(op)->data.any) #undef PyUnicode_READY #define PyUnicode_READY(op) \ @@ -190,7 +190,7 @@ extern "C" { buffer where the result characters are written to. */ #define _PyUnicode_CONVERT_BYTES(from_type, to_type, begin, end, to) \ do { \ - to_type *_to = (to_type *)(to); \ + to_type *_to = (to_type *)(to); \ const from_type *_iter = (const from_type *)(begin);\ const from_type *_end = (const from_type *)(end);\ Py_ssize_t n = (_end) - (_iter); \ @@ -509,21 +509,18 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) #define CHECK(expr) \ do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0) - PyASCIIObject *ascii; - unsigned int kind; - assert(op != NULL); CHECK(PyUnicode_Check(op)); - ascii = (PyASCIIObject *)op; - kind = ascii->state.kind; + PyASCIIObject *ascii = _PyASCIIObject_CAST(op); + unsigned int kind = ascii->state.kind; if (ascii->state.ascii == 1 && ascii->state.compact == 1) { CHECK(kind == PyUnicode_1BYTE_KIND); CHECK(ascii->state.ready == 1); } else { - PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; + PyCompactUnicodeObject *compact = _PyCompactUnicodeObject_CAST(op); void *data; if (ascii->state.compact == 1) { @@ -536,7 +533,7 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) CHECK(compact->utf8 != data); } else { - PyUnicodeObject *unicode = (PyUnicodeObject *)op; + PyUnicodeObject *unicode = _PyUnicodeObject_CAST(op); data = unicode->data.any; if (kind == PyUnicode_WCHAR_KIND) { @@ -1330,8 +1327,8 @@ const void *_PyUnicode_data(void *unicode_raw) { printf("obj %p\n", (void*)unicode); printf("compact %d\n", PyUnicode_IS_COMPACT(unicode)); printf("compact ascii %d\n", PyUnicode_IS_COMPACT_ASCII(unicode)); - printf("ascii op %p\n", ((void*)((PyASCIIObject*)(unicode) + 1))); - printf("compact op %p\n", ((void*)((PyCompactUnicodeObject*)(unicode) + 1))); + printf("ascii op %p\n", (void*)(_PyASCIIObject_CAST(unicode) + 1)); + printf("compact op %p\n", (void*)(_PyCompactUnicodeObject_CAST(unicode) + 1)); printf("compact data %p\n", _PyUnicode_COMPACT_DATA(unicode)); return PyUnicode_DATA(unicode); } @@ -1339,9 +1336,9 @@ const void *_PyUnicode_data(void *unicode_raw) { void _PyUnicode_Dump(PyObject *op) { - PyASCIIObject *ascii = (PyASCIIObject *)op; - PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; - PyUnicodeObject *unicode = (PyUnicodeObject *)op; + PyASCIIObject *ascii = _PyASCIIObject_CAST(op); + PyCompactUnicodeObject *compact = _PyCompactUnicodeObject_CAST(op); + PyUnicodeObject *unicode = _PyUnicodeObject_CAST(op); const void *data; if (ascii->state.compact) @@ -1976,7 +1973,7 @@ unicode_is_singleton(PyObject *unicode) return 1; } - PyASCIIObject *ascii = (PyASCIIObject *)unicode; + PyASCIIObject *ascii = _PyASCIIObject_CAST(unicode); if (ascii->state.kind != PyUnicode_WCHAR_KIND && ascii->length == 1) { Py_UCS4 ch = PyUnicode_READ_CHAR(unicode, 0); if (ch < 256 && LATIN1(ch) == unicode) { @@ -16053,7 +16050,7 @@ _PyUnicode_FiniTypes(PyInterpreterState *interp) static void unicode_static_dealloc(PyObject *op) { - PyASCIIObject* ascii = (PyASCIIObject*)op; + PyASCIIObject *ascii = _PyASCIIObject_CAST(op); assert(ascii->state.compact); diff --git a/Python/traceback.c b/Python/traceback.c index 6a721cf..f5c1849 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -1073,7 +1073,7 @@ _Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width) void _Py_DumpASCII(int fd, PyObject *text) { - PyASCIIObject *ascii = (PyASCIIObject *)text; + PyASCIIObject *ascii = _PyASCIIObject_CAST(text); Py_ssize_t i, size; int truncated; int kind; @@ -1087,19 +1087,19 @@ _Py_DumpASCII(int fd, PyObject *text) size = ascii->length; kind = ascii->state.kind; if (kind == PyUnicode_WCHAR_KIND) { - wstr = ((PyASCIIObject *)text)->wstr; + wstr = ascii->wstr; if (wstr == NULL) return; - size = ((PyCompactUnicodeObject *)text)->wstr_length; + size = _PyCompactUnicodeObject_CAST(text)->wstr_length; } else if (ascii->state.compact) { if (ascii->state.ascii) - data = ((PyASCIIObject*)text) + 1; + data = ascii + 1; else - data = ((PyCompactUnicodeObject*)text) + 1; + data = _PyCompactUnicodeObject_CAST(text) + 1; } else { - data = ((PyUnicodeObject *)text)->data.any; + data = _PyUnicodeObject_CAST(text)->data.any; if (data == NULL) return; } |