From 3c64fa3e2cbc749543dada61ce7aa93d4c3beacc Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Sat, 4 Jun 2022 18:49:39 -0700 Subject: [PATCH] gh-93442: Make C++ version of _Py_CAST work with 0/NULL. (GH-93500) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add C++ overloads for _Py_CAST_impl() to handle 0/NULL. This will allow C++ extensions that pass 0 or NULL to macros using _Py_CAST() to continue to compile. Without this, you get an error like: invalid ‘static_cast’ from type ‘int’ to type ‘_object*’ The modern way to use a NULL value in C++ is to use nullptr. However, we want to not break extensions that do things the old way. Co-authored-by: serge-sans-paille (cherry picked from commit 8bcc3fa3453e28511d04eaa0aa7d8e1a3495d518) Co-authored-by: Neil Schemenauer --- Include/pyport.h | 14 ++++++++++++++ Lib/test/_testcppext.cpp | 4 ++++ .../2022-06-04-13-15-41.gh-issue-93442.4M4NDb.rst | 3 +++ 3 files changed, 21 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2022-06-04-13-15-41.gh-issue-93442.4M4NDb.rst diff --git a/Include/pyport.h b/Include/pyport.h index 5a9adf162bfd9d..a78e290931fffe 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -24,9 +24,23 @@ // // The type argument must not be a constant type. #ifdef __cplusplus +#include # define _Py_STATIC_CAST(type, expr) static_cast(expr) extern "C++" { namespace { + template + inline type _Py_CAST_impl(long int ptr) { + return reinterpret_cast(ptr); + } + template + inline type _Py_CAST_impl(int ptr) { + return reinterpret_cast(ptr); + } + template + inline type _Py_CAST_impl(std::nullptr_t) { + return static_cast(nullptr); + } + template inline type _Py_CAST_impl(expr_type *expr) { return reinterpret_cast(expr); diff --git a/Lib/test/_testcppext.cpp b/Lib/test/_testcppext.cpp index eade7ccdaaff7a..70f434e6789ad7 100644 --- a/Lib/test/_testcppext.cpp +++ b/Lib/test/_testcppext.cpp @@ -74,6 +74,10 @@ test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) Py_INCREF(strong_ref); Py_DECREF(strong_ref); + // gh-93442: Pass 0 as NULL for PyObject* + Py_XINCREF(0); + Py_XDECREF(0); + Py_DECREF(obj); Py_RETURN_NONE; } diff --git a/Misc/NEWS.d/next/C API/2022-06-04-13-15-41.gh-issue-93442.4M4NDb.rst b/Misc/NEWS.d/next/C API/2022-06-04-13-15-41.gh-issue-93442.4M4NDb.rst new file mode 100644 index 00000000000000..f48ed37c814454 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-06-04-13-15-41.gh-issue-93442.4M4NDb.rst @@ -0,0 +1,3 @@ +Add C++ overloads for _Py_CAST_impl() to handle 0/NULL. This will allow C++ +extensions that pass 0 or NULL to macros using _Py_CAST() to continue to +compile.