Title: [C API] Avoid "const PyObject*" type · Issue #91768 · python/cpython · GitHub
Open Graph Title: [C API] Avoid "const PyObject*" type · Issue #91768 · python/cpython
X Title: [C API] Avoid "const PyObject*" type · Issue #91768 · python/cpython
Description: When I converted Py_REFCNT(), Py_TYPE() and Py_SIZE() macros to static inline functions (issue #83754), I chose const PyObject* for their argument because these macros don't modify any member of the PyObject structure. When the Py_IS_TYP...
Open Graph Description: When I converted Py_REFCNT(), Py_TYPE() and Py_SIZE() macros to static inline functions (issue #83754), I chose const PyObject* for their argument because these macros don't modify any member of th...
X Description: When I converted Py_REFCNT(), Py_TYPE() and Py_SIZE() macros to static inline functions (issue #83754), I chose const PyObject* for their argument because these macros don't modify any member o...
Opengraph URL: https://github.com/python/cpython/issues/91768
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[C API] Avoid \"const PyObject*\" type","articleBody":"When I converted ``Py_REFCNT()``, ``Py_TYPE()`` and ``Py_SIZE()`` macros to static inline functions (issue #83754), I chose ``const PyObject*`` for their argument because these macros don't modify any member of the PyObject structure. When the Py_IS_TYPE() function was added, it followed the trend (commit 8767ce92d24d3687405848442e6c67cf0af1c657). The ``_PyObject_CAST_CONST()`` macro was added to easily convert any pointer to ``const PyObject*`` for these macros expecting ``const PyObject*``.\r\n\r\nThe problem is that passing ``PyObject*`` to one of these functions emits a compiler warning using ``gcc -Wcast-qual``. The ``_PyObject_CAST_CONST()`` doesn't make the warning quiet.\r\n\r\nExample explaining the issue:\r\n\r\n```c\r\nstatic inline int value(int *p) { return *p; }\r\n#define value(p) value((int*)(p))\r\n\r\nint main()\r\n{\r\n int x = 1;\r\n const int *p = \u0026x;\r\n return value(p);\r\n}\r\n```\r\n\r\nOutput:\r\n\r\n```sh\r\n$ gcc x.c -Wcast-qual -o x \u0026\u0026 ./x; echo $?\r\nx.c: In function 'main':\r\nx.c:2:24: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]\r\n 2 | #define value(p) value((int*)(p))\r\n | ^\r\nx.c:8:12: note: in expansion of macro 'value'\r\n 8 | return value(p);\r\n | ^~~~~\r\n1\r\n```\r\n\r\nIn practice, the problem was that building a C extension (which includes ``\u003cPython.h\u003e``) with ``gcc -Wcast-qual -Werror`` on Python 3.10 failed with an error on Py_IS_TYPE() implemented as:\r\n\r\n```c\r\nstatic inline int Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {\r\n return Py_TYPE(ob) == type;\r\n}\r\n#define Py_IS_TYPE(ob, type) Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)\r\n```\r\n\r\nSee the issue #88544 for the compiler error. I removed the Py_TYPE() call in Py_IS_TYPE() to work around the issue:\r\n\r\n```c\r\nstatic inline int Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {\r\n // bpo-44378: Don't use Py_TYPE() since Py_TYPE() requires a non-const\r\n // object.\r\n return ob-\u003eob_type == type;\r\n}\r\n#define Py_IS_TYPE(ob, type) Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)\r\n```\r\n\r\nBut this problem strikes back when I try to convert unicodeobject.h macros to static inline functions for PEP 670 which removes the cast to ``PyObject*`` in the limited C API version 3.11: see PR #91696 and PR #91705. For example, _Py_strhex_with_sep() and _Py_strhex_bytes_with_sep() function get a ``const PyObject*`` argument and use PyUnicode C functions like PyUnicode_READY(), PyUnicode_KIND() and PyUnicode_READ_CHAR(), but these PyUnicode functions expect ``PyObject*``: the ``const`` qualifier is lost. If Python/pystrhex.c is built with ``gcc -Wcast-qual``, gcc emits warnings on PyUnicode_KIND() and PyUnicode_READ_CHAR() calls. That's just an example of problem which can happen in C extensions as well.\r\n\r\nTo avoid these problems, I propose to avoid ``const PyObject*`` in Python: only use ``PyObject*``.","author":{"url":"https://github.com/vstinner","@type":"Person","name":"vstinner"},"datePublished":"2022-04-20T23:37:07.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/91768/cpython/issues/91768"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:12ec53b5-483e-949c-9c25-742a87157bca |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D930:C563C:B4724:F9B2C:696A615A |
| html-safe-nonce | cdbd04b1013e93375cc18ba6422b1ee0ffadf077810528d2f6cb5f7cf938b9a0 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEOTMwOkM1NjNDOkI0NzI0OkY5QjJDOjY5NkE2MTVBIiwidmlzaXRvcl9pZCI6IjUyNzgxMDEyNDE4NTY2ODAyODIiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | bd9a4dd72e9795c2321301eb92b6c1a231a3a17170325756c0208544fca6bb30 |
| hovercard-subject-tag | issue:1210326060 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/91768/issue_layout |
| twitter:image | https://opengraph.githubassets.com/481be8b2abe8194361d89d5b88e04e85412d51fea9cde88dafb1cb05c91fd35a/python/cpython/issues/91768 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/481be8b2abe8194361d89d5b88e04e85412d51fea9cde88dafb1cb05c91fd35a/python/cpython/issues/91768 |
| og:image:alt | When I converted Py_REFCNT(), Py_TYPE() and Py_SIZE() macros to static inline functions (issue #83754), I chose const PyObject* for their argument because these macros don't modify any member of th... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | vstinner |
| hostname | github.com |
| expected-hostname | github.com |
| None | 9b7735a184970dd9333b2cbe036c8f3c0a9108c64aaa93827c5a64fc70993392 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 87cbd411c2982752221b5751d583a515b23bf5fa |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width