Skip to content

Commit

Permalink
Make _Py_Cast C++ version compatible with cast operator
Browse files Browse the repository at this point in the history
Use the adequate kind of cast based on the macro argument: const ref, cont
pointer, ref or pointer.

This should be compatible with C++ overloads.

Fix python#92898
  • Loading branch information
serge-sans-paille committed May 19, 2022
1 parent 4163896 commit 636d461
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
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

0 comments on commit 636d461

Please sign in to comment.