Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[3.11] GH-92898: Make _Py_Cast C++ version compatible with cast opera…
…tor (gh-92951)

(cherry picked from commit 5b71b51)

Co-authored-by: serge-sans-paille <[email protected]>
  • Loading branch information
serge-sans-paille authored and corona10 committed May 21, 2022
commit 1190ed125bf9194504d32bb2b6089448c92cc190
28 changes: 26 additions & 2 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,32 @@
// _Py_CAST(const PyObject*, expr) fails with a compiler error.
#ifdef __cplusplus
# define _Py_STATIC_CAST(type, expr) static_cast<type>(expr)
# define _Py_CAST(type, expr) \
const_cast<type>(reinterpret_cast<const type>(expr))

extern "C++" {
namespace {
template <typename type, typename expr_type>
inline type _Py_reinterpret_cast_impl(expr_type *expr) {
return reinterpret_cast<type>(expr);
}

template <typename type, typename expr_type>
inline type _Py_reinterpret_cast_impl(expr_type const *expr) {
return reinterpret_cast<type>(const_cast<expr_type *>(expr));
}

template <typename type, typename expr_type>
inline type _Py_reinterpret_cast_impl(expr_type &expr) {
return static_cast<type>(expr);
}

template <typename type, typename expr_type>
inline type _Py_reinterpret_cast_impl(expr_type const &expr) {
return static_cast<type>(const_cast<expr_type &>(expr));
}
} // namespace
}
# define _Py_CAST(type, expr) _Py_reinterpret_cast_impl<type>(expr)

#else
# define _Py_STATIC_CAST(type, expr) ((type)(expr))
# define _Py_CAST(type, expr) ((type)(expr))
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/_testcppext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
PyTypeObject *type = Py_TYPE(const_obj);
assert(Py_REFCNT(const_obj) >= 1);

struct PyObjectProxy {
PyObject* obj;
operator PyObject *() { return obj; }
} proxy_obj = { obj };
Py_INCREF(proxy_obj);
Py_DECREF(proxy_obj);
assert(Py_REFCNT(proxy_obj) >= 1);


assert(type == &PyTuple_Type);
assert(PyTuple_GET_SIZE(const_obj) == 2);
PyObject *one = PyTuple_GET_ITEM(const_obj, 0);
Expand Down