Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0313970

Browse files
authored
gh-92135: Fix _Py_reinterpret_cast() for const (#92138)
Fix C++ compiler warnings on cast macros, like _PyObject_CAST(), whencasting a constant expression to a non constant type: useconst_cast<> in C++.* In C++, Py_SAFE_DOWNCAST() now uses static_cast<> rather than reinterpret_cast<>.* Add tests to the _testcppext C++ extension.* test_cppext no longer captures stdout in verbose mode.
1 parentb11243e commit0313970

File tree

5 files changed

+62
-14
lines changed

5 files changed

+62
-14
lines changed

‎Include/methodobject.h‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ typedef PyObject *(*PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *,
4343
// it triggers an undefined behavior when Python calls it with 2 parameters
4444
// (bpo-33012).
4545
#define_PyCFunction_CAST(func) \
46-
_Py_reinterpret_cast(PyCFunction, \
47-
_Py_reinterpret_cast(void(*)(void), (func)))
46+
_Py_reinterpret_cast(PyCFunction, _Py_reinterpret_cast(void(*)(void), (func)))
4847

4948
PyAPI_FUNC(PyCFunction)PyCFunction_GetFunction(PyObject*);
5049
PyAPI_FUNC(PyObject*)PyCFunction_GetSelf(PyObject*);

‎Include/objimpl.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,9 @@ PyAPI_FUNC(void) PyObject_GC_UnTrack(void *);
182182
PyAPI_FUNC(void)PyObject_GC_Del(void*);
183183

184184
#definePyObject_GC_New(type,typeobj) \
185-
_Py_reinterpret_cast(type*, _PyObject_GC_New(typeobj))
185+
_Py_reinterpret_cast(type*, _PyObject_GC_New(typeobj))
186186
#definePyObject_GC_NewVar(type,typeobj,n) \
187-
_Py_reinterpret_cast(type*, _PyObject_GC_NewVar((typeobj), (n)))
187+
_Py_reinterpret_cast(type*, _PyObject_GC_NewVar((typeobj), (n)))
188188

189189
PyAPI_FUNC(int)PyObject_GC_IsTracked(PyObject*);
190190
PyAPI_FUNC(int)PyObject_GC_IsFinalized(PyObject*);

‎Include/pyport.h‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,20 @@
1414
#endif
1515

1616

17-
// Macro to use C++ static_cast<> and reinterpret_cast<> in the Python C API
17+
// Macro to use C++ static_cast<>, reinterpret_cast<> and const_cast<>
18+
// in the Python C API.
19+
//
20+
// In C++, _Py_reinterpret_cast(type, expr) converts a constant expression to a
21+
// non constant type using const_cast<type>. For example,
22+
// _Py_reinterpret_cast(PyObject*, op) can convert a "const PyObject*" to
23+
// "PyObject*".
24+
//
25+
// The type argument must not be constant. For example, in C++,
26+
// _Py_reinterpret_cast(const PyObject*, expr) fails with a compiler error.
1827
#ifdef__cplusplus
1928
# define_Py_static_cast(type,expr) static_cast<type>(expr)
20-
# define_Py_reinterpret_cast(type,expr) reinterpret_cast<type>(expr)
29+
# define_Py_reinterpret_cast(type,expr) \
30+
const_cast<type>(reinterpret_cast<const type>(expr))
2131
#else
2232
# define_Py_static_cast(type,expr) ((type)(expr))
2333
# define_Py_reinterpret_cast(type,expr) ((type)(expr))
@@ -307,10 +317,10 @@ extern "C" {
307317
*/
308318
#ifdefPy_DEBUG
309319
# definePy_SAFE_DOWNCAST(VALUE,WIDE,NARROW) \
310-
(assert((WIDE)(NARROW)(VALUE) == (VALUE)), (NARROW)(VALUE))
320+
(assert(_Py_static_cast(WIDE, _Py_static_cast(NARROW, (VALUE))) == (VALUE)), \
321+
_Py_static_cast(NARROW, (VALUE)))
311322
#else
312-
# definePy_SAFE_DOWNCAST(VALUE,WIDE,NARROW) \
313-
_Py_reinterpret_cast(NARROW, (VALUE))
323+
# definePy_SAFE_DOWNCAST(VALUE,WIDE,NARROW) _Py_static_cast(NARROW, (VALUE))
314324
#endif
315325

316326

‎Lib/test/_testcppext.cpp‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// gh-91321: Very basic C++ test extension to check that the Python C API is
22
// compatible with C++ and does not emit C++ compiler warnings.
33

4+
// Always enable assertions
5+
#undef NDEBUG
6+
47
#include"Python.h"
58

69
PyDoc_STRVAR(_testcppext_add_doc,
@@ -20,8 +23,36 @@ _testcppext_add(PyObject *Py_UNUSED(module), PyObject *args)
2023
}
2124

2225

26+
static PyObject *
27+
test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
28+
{
29+
PyObject *obj =Py_BuildValue("(ii)",1,2);
30+
if (obj ==nullptr) {
31+
returnnullptr;
32+
}
33+
34+
// gh-92138: For backward compatibility, functions of Python C API accepts
35+
// "const PyObject*". Check that using it does not emit C++ compiler
36+
// warnings.
37+
const PyObject *const_obj = obj;
38+
Py_INCREF(const_obj);
39+
Py_DECREF(const_obj);
40+
PyTypeObject *type =Py_TYPE(const_obj);
41+
assert(Py_REFCNT(const_obj) >=1);
42+
43+
assert(type == &PyTuple_Type);
44+
assert(PyTuple_GET_SIZE(const_obj) ==2);
45+
PyObject *one =PyTuple_GET_ITEM(const_obj,0);
46+
assert(PyLong_AsLong(one) ==1);
47+
48+
Py_DECREF(obj);
49+
Py_RETURN_NONE;
50+
}
51+
52+
2353
static PyMethodDef _testcppext_methods[] = {
2454
{"add", _testcppext_add, METH_VARARGS, _testcppext_add_doc},
55+
{"test_api_casts", test_api_casts, METH_NOARGS,NULL},
2556
{nullptr,nullptr,0,nullptr}/* sentinel*/
2657
};
2758

‎Lib/test/test_cppext.py‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# gh-91321: Build a basic C++ test extension to check that the Python C API is
22
# compatible with C++ and does not emit C++ compiler warnings.
3+
importcontextlib
34
importos
45
importsys
56
importunittest
@@ -39,17 +40,24 @@ def build(self):
3940
sources=[SOURCE],
4041
language='c++',
4142
extra_compile_args=CPPFLAGS)
43+
capture_stdout= (notsupport.verbose)
4244

4345
try:
4446
try:
45-
with (support.captured_stdout()asstdout,
46-
support.swap_attr(sys,'argv', ['setup.py','build_ext'])):
47+
ifcapture_stdout:
48+
stdout=support.captured_stdout()
49+
else:
50+
print()
51+
stdout=contextlib.nullcontext()
52+
with (stdout,
53+
support.swap_attr(sys,'argv', ['setup.py','build_ext','--verbose'])):
4754
setup(name="_testcppext",ext_modules=[cpp_ext])
4855
return
4956
except:
50-
# Show output on error
51-
print()
52-
print(stdout.getvalue())
57+
ifcapture_stdout:
58+
# Show output on error
59+
print()
60+
print(stdout.getvalue())
5361
raise
5462
exceptSystemExit:
5563
self.fail("Build failed")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp