From 8e7307f0699726c29f5bdc2c177dd55b6b330061 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Wed, 24 Jul 2024 05:32:39 +0300 Subject: [PATCH 1/5] docs: remove outdated known limitation. (#5263) * Fix typo. * Remove outdated known limitation. See #5179. --- docs/limitations.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/limitations.rst b/docs/limitations.rst index def5ad65..1b06ea87 100644 --- a/docs/limitations.rst +++ b/docs/limitations.rst @@ -50,10 +50,6 @@ clean, well written patch would likely be accepted to solve them. One consequence is that containers of ``char *`` are currently not supported. `#2245 `_ -- The ``cpptest`` does not run on Windows with Python 3.8 or newer, due to DLL - loader changes. User code that is correctly installed should not be affected. - `#2560 `_ - Python 3.9.0 warning ^^^^^^^^^^^^^^^^^^^^ From 2e260b067f565ecd7f8427667ef2f384eceb7f12 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 30 Jul 2024 01:10:03 +0700 Subject: [PATCH 2/5] clang-tidy upgrade (to version 18) (#5272) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `container: silkeh/clang:18-bookworm` in .github/workflows/format.yml * clang-tidy auto-fix (trivial, in test only) * Disable `performance-enum-size` (noisy, low value) * Temporarily turn off 3 diagnostics (to be tackled one-by-one). * Add explicit `switch` `default` to resolve clang-tidy `bugprone-switch-missing-default-case` Debian clang version 18.1.8 (++20240718080534+3b5b5c1ec4a3-1~exp1~20240718200641.143) Target: x86_64-pc-linux-gnu tests/test_numpy_dtypes.cpp:212:5: warning: switching on non-enum value without default case may not cover all cases [bugprone-switch-missing-default-case] * Add clang-17 and clang-18 testing. * Add `NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)` in test_tagbased_polymorphic.cpp Debian clang version 18.1.8 (++20240718080534+3b5b5c1ec4a3-1~exp1~20240718200641.143) Target: x86_64-pc-linux-gnu tests/test_tagbased_polymorphic.cpp:77:40: warning: The value '150' provided to the cast expression is not in the valid range of values for 'Kind' [clang-analyzer-optin.core.EnumCastOutOfRange] * Fix inconsistent pybind11/eigen/tensor.h behavior: This existing comment in pybind11/eigen/tensor.h ``` // move, take_ownership don't make any sense for a ref/map: ``` is at odds with the `delete src;` three lines up. In real-world client code `take_ownership` will not exist (unless the client code is untested and unused). I.e. the `delete` is essentially only useful to avoid leaks in the pybind11 unit tests. While upgrading to clang-tidy 18, the warning below appeared. Apparently it is produced during LTO, and it appears difficult to suppress. Regardless, the best way to resolve this is to remove the `delete` and to simply make the test objects `static` in the unit test code. ________ Debian clang version 18.1.8 (++20240718080534+3b5b5c1ec4a3-1~exp1~20240718200641.143) Target: x86_64-pc-linux-gnu ________ ``` lto-wrapper: warning: using serial compilation of 3 LTRANS jobs lto-wrapper: note: see the ‘-flto’ option documentation for more information In function ‘cast_impl’, inlined from ‘cast’ at /mounted_pybind11/include/pybind11/eigen/tensor.h:414:25, inlined from ‘operator()’ at /mounted_pybind11/include/pybind11/eigen/../pybind11.h:296:40, inlined from ‘_FUN’ at /mounted_pybind11/include/pybind11/eigen/../pybind11.h:267:21: /mounted_pybind11/include/pybind11/eigen/tensor.h:475:17: warning: ‘operator delete’ called on unallocated object ‘’ [-Wfree-nonheap-object] 475 | delete src; | ^ /mounted_pybind11/include/pybind11/eigen/../pybind11.h: In function ‘_FUN’: /mounted_pybind11/include/pybind11/eigen/../pybind11.h:297:75: note: declared here 297 | std::move(args_converter).template call(cap->f), | ^ ``` * Disable `bugprone-chained-comparison`: this clang-tidy check is incompatible with the Catch2 `REQUIRE` macro (26 warnings like the one below). ________ Debian clang version 18.1.8 (++20240718080534+3b5b5c1ec4a3-1~exp1~20240718200641.143) Target: x86_64-pc-linux-gnu ________ ``` /mounted_pybind11/tests/test_embed/test_interpreter.cpp:127:9: warning: chained comparison 'v0 <= v1 == v2' may generate unintended results, use parentheses to specify order of evaluation or a logical operator to separate comparison expressions [bugprone-chained-comparison] 127 | REQUIRE(ret == 42); | ^ /build/tests/catch/catch.hpp:17670:24: note: expanded from macro 'REQUIRE' 17670 | #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /build/tests/catch/catch.hpp:2710:47: note: expanded from macro 'INTERNAL_CATCH_TEST' 2710 | catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /mounted_pybind11/tests/test_embed/test_interpreter.cpp:127:9: note: operand 'v0' is here 127 | REQUIRE(ret == 42); | ^ /build/tests/catch/catch.hpp:17670:24: note: expanded from macro 'REQUIRE' 17670 | #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /build/tests/catch/catch.hpp:2710:47: note: expanded from macro 'INTERNAL_CATCH_TEST' 2710 | catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ | ^~~~~~~~~~~~~~~~~~~ /mounted_pybind11/tests/test_embed/test_interpreter.cpp:127:17: note: operand 'v1' is here 127 | REQUIRE(ret == 42); | ^ /build/tests/catch/catch.hpp:17670:90: note: expanded from macro 'REQUIRE' 17670 | #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ^~~~~~~~~~~ /build/tests/catch/catch.hpp:2710:70: note: expanded from macro 'INTERNAL_CATCH_TEST' 2710 | catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ | ^~~~~~~~~~~ /mounted_pybind11/tests/test_embed/test_interpreter.cpp:127:24: note: operand 'v2' is here 127 | REQUIRE(ret == 42); | ^ /build/tests/catch/catch.hpp:17670:90: note: expanded from macro 'REQUIRE' 17670 | #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ^~~~~~~~~~~ /build/tests/catch/catch.hpp:2710:70: note: expanded from macro 'INTERNAL_CATCH_TEST' 2710 | catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ | ^~~~~~~~~~~ ``` * Add 8 `// NOLINT(bugprone-empty-catch)` * Resolve clang-tidy `bugprone-multi-level-implicit-pointer-conversion` warnings. ________ Debian clang version 18.1.8 (++20240718080534+3b5b5c1ec4a3-1~exp1~20240718200641.143) Target: x86_64-pc-linux-gnu ________ ``` pybind11/detail/internals.h:556:53: warning: multilevel pointer conversion from 'internals **' to 'const void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] pybind11/detail/type_caster_base.h:431:20: warning: multilevel pointer conversion from 'void **' to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] pybind11/numpy.h:904:81: warning: multilevel pointer conversion from '_object *const *' to 'const void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] pybind11/numpy.h:1989:39: warning: multilevel pointer conversion from 'typename vectorize_arg::type *' (aka 'const double **') to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] pybind11/numpy.h:1989:39: warning: multilevel pointer conversion from 'typename vectorize_arg::type *' (aka 'const VectorizeTestClass **') to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] pybind11/stl/filesystem.h:75:44: warning: multilevel pointer conversion from 'PyObject **' (aka '_object **') to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] pybind11/stl/filesystem.h:83:42: warning: multilevel pointer conversion from 'PyObject **' (aka '_object **') to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion] ``` * Introduce `PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY` to resolve PyPy build errors: ``` In file included from /Users/runner/work/pybind11/pybind11/tests/test_stl.cpp:18: /Users/runner/work/pybind11/pybind11/include/pybind11/stl/filesystem.h:75:17: error: no matching function for call to 'PyPyUnicode_FSConverter' if (PyUnicode_FSConverter(buf, reinterpret_cast(&native)) != 0) { ^~~~~~~~~~~~~~~~~~~~~ /Users/runner/hostedtoolcache/PyPy/3.10.14/x64/include/pypy3.10/pypy_decl.h:969:31: note: expanded from macro 'PyUnicode_FSConverter' ^~~~~~~~~~~~~~~~~~~~~~~ /Users/runner/hostedtoolcache/PyPy/3.10.14/x64/include/pypy3.10/pypy_decl.h:970:17: note: candidate function not viable: cannot convert argument of incomplete type 'void *' to 'struct _object **' for 2nd argument PyAPI_FUNC(int) PyUnicode_FSConverter(struct _object *arg0, struct _object **arg1); ^ /Users/runner/hostedtoolcache/PyPy/3.10.14/x64/include/pypy3.10/pypy_decl.h:969:31: note: expanded from macro 'PyUnicode_FSConverter' ^ In file included from /Users/runner/work/pybind11/pybind11/tests/test_stl.cpp:18: /Users/runner/work/pybind11/pybind11/include/pybind11/stl/filesystem.h:83:17: error: no matching function for call to 'PyPyUnicode_FSDecoder' if (PyUnicode_FSDecoder(buf, reinterpret_cast(&native)) != 0) { ^~~~~~~~~~~~~~~~~~~ /Users/runner/hostedtoolcache/PyPy/3.10.14/x64/include/pypy3.10/pypy_decl.h:971:29: note: expanded from macro 'PyUnicode_FSDecoder' ^~~~~~~~~~~~~~~~~~~~~ /Users/runner/hostedtoolcache/PyPy/3.10.14/x64/include/pypy3.10/pypy_decl.h:972:17: note: candidate function not viable: cannot convert argument of incomplete type 'void *' to 'struct _object **' for 2nd argument PyAPI_FUNC(int) PyUnicode_FSDecoder(struct _object *arg0, struct _object **arg1); ^ /Users/runner/hostedtoolcache/PyPy/3.10.14/x64/include/pypy3.10/pypy_decl.h:971:29: note: expanded from macro 'PyUnicode_FSDecoder' ^ ``` * clang-tidy auto-fix * Fix silly oversight. --- .clang-tidy | 2 ++ .github/workflows/ci.yml | 6 ++++++ .github/workflows/format.yml | 2 +- include/pybind11/detail/internals.h | 2 +- include/pybind11/detail/type_caster_base.h | 2 +- include/pybind11/eigen/tensor.h | 3 --- include/pybind11/numpy.h | 8 ++++++-- include/pybind11/stl/filesystem.h | 13 +++++++++++-- include/pybind11/stl_bind.h | 2 +- tests/constructor_stats.h | 2 +- tests/test_eigen_tensor.inl | 16 +++++++++++----- tests/test_modules.cpp | 12 ++++++------ tests/test_numpy_dtypes.cpp | 2 ++ tests/test_opaque_types.cpp | 2 +- tests/test_tagbased_polymorphic.cpp | 1 + 15 files changed, 51 insertions(+), 24 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 23018386..96cb6f58 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -57,10 +57,12 @@ Checks: | readability-string-compare, readability-suspicious-call-argument, readability-uniqueptr-delete-release, + -bugprone-chained-comparison, -bugprone-easily-swappable-parameters, -bugprone-exception-escape, -bugprone-reserved-identifier, -bugprone-unused-raii, + -performance-enum-size, CheckOptions: - key: modernize-use-equals-default.IgnoreMacros diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 041e0dfb..06c53bf1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -340,6 +340,12 @@ jobs: - clang: 16 std: 20 container_suffix: "-bullseye" + - clang: 17 + std: 20 + container_suffix: "-bookworm" + - clang: 18 + std: 20 + container_suffix: "-bookworm" name: "🐍 3 • Clang ${{ matrix.clang }} • C++${{ matrix.std }} • x64" container: "silkeh/clang:${{ matrix.clang }}${{ matrix.container_suffix }}" diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 1eaa56e1..e50dc0bb 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -41,7 +41,7 @@ jobs: # in .github/CONTRIBUTING.md and update as needed. name: Clang-Tidy runs-on: ubuntu-latest - container: silkeh/clang:15-bullseye + container: silkeh/clang:18-bookworm steps: - uses: actions/checkout@v4 diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 3f0a6a94..692e8d39 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -553,7 +553,7 @@ PYBIND11_NOINLINE internals &get_internals() { } #endif internals_ptr->istate = tstate->interp; - state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp); + state_dict[PYBIND11_INTERNALS_ID] = capsule(reinterpret_cast(internals_pp)); internals_ptr->registered_exception_translators.push_front(&translate_exception); internals_ptr->static_property_type = make_static_property_type(); internals_ptr->default_metaclass = make_default_metaclass(); diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index 1b57ee83..481b7c78 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -428,7 +428,7 @@ PYBIND11_NOINLINE void instance::allocate_layout() { // NOLINTNEXTLINE(readability-make-member-function-const) PYBIND11_NOINLINE void instance::deallocate_layout() { if (!simple_layout) { - PyMem_Free(nonsimple.values_and_holders); + PyMem_Free(reinterpret_cast(nonsimple.values_and_holders)); } } diff --git a/include/pybind11/eigen/tensor.h b/include/pybind11/eigen/tensor.h index d4ed6c0c..14bb91c4 100644 --- a/include/pybind11/eigen/tensor.h +++ b/include/pybind11/eigen/tensor.h @@ -469,9 +469,6 @@ struct type_caster, parent_object = reinterpret_borrow(parent); break; - case return_value_policy::take_ownership: - delete src; - // fallthrough default: // move, take_ownership don't make any sense for a ref/map: pybind11_fail("Invalid return_value_policy for Eigen Map type, must be either " diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 05ef3918..09894cf7 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -901,7 +901,11 @@ class array : public buffer { template array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle()) - : array(pybind11::dtype::of(), std::move(shape), std::move(strides), ptr, base) {} + : array(pybind11::dtype::of(), + std::move(shape), + std::move(strides), + reinterpret_cast(ptr), + base) {} template array(ShapeContainer shape, const T *ptr, handle base = handle()) @@ -1986,7 +1990,7 @@ struct vectorize_helper { // Pointers to values the function was called with; the vectorized ones set here will start // out as array_t pointers, but they will be changed them to T pointers before we make // call the wrapped function. Non-vectorized pointers are left as-is. - std::array params{{&args...}}; + std::array params{{reinterpret_cast(&args)...}}; // The array of `buffer_info`s of vectorized arguments: std::array buffers{ diff --git a/include/pybind11/stl/filesystem.h b/include/pybind11/stl/filesystem.h index 85c131ef..935d7948 100644 --- a/include/pybind11/stl/filesystem.h +++ b/include/pybind11/stl/filesystem.h @@ -33,6 +33,13 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) +#ifdef PYPY_VERSION +# define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) (__VA_ARGS__) +#else +# define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) \ + (reinterpret_cast(__VA_ARGS__)) +#endif + #if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) template struct path_caster { @@ -72,7 +79,8 @@ struct path_caster { } PyObject *native = nullptr; if constexpr (std::is_same_v) { - if (PyUnicode_FSConverter(buf, &native) != 0) { + if (PyUnicode_FSConverter(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native)) + != 0) { if (auto *c_str = PyBytes_AsString(native)) { // AsString returns a pointer to the internal buffer, which // must not be free'd. @@ -80,7 +88,8 @@ struct path_caster { } } } else if constexpr (std::is_same_v) { - if (PyUnicode_FSDecoder(buf, &native) != 0) { + if (PyUnicode_FSDecoder(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native)) + != 0) { if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) { // AsWideCharString returns a new string that must be free'd. value = c_str; // Copies the string. diff --git a/include/pybind11/stl_bind.h b/include/pybind11/stl_bind.h index 66c452ea..fcb48dea 100644 --- a/include/pybind11/stl_bind.h +++ b/include/pybind11/stl_bind.h @@ -180,7 +180,7 @@ void vector_modifiers( v.end()); try { v.shrink_to_fit(); - } catch (const std::exception &) { + } catch (const std::exception &) { // NOLINT(bugprone-empty-catch) // Do nothing } throw; diff --git a/tests/constructor_stats.h b/tests/constructor_stats.h index 937f6c23..9a5754fe 100644 --- a/tests/constructor_stats.h +++ b/tests/constructor_stats.h @@ -190,7 +190,7 @@ class ConstructorStats { t1 = &p.first; } } - } catch (const std::out_of_range &) { + } catch (const std::out_of_range &) { // NOLINT(bugprone-empty-catch) } if (!t1) { throw std::runtime_error("Unknown class passed to ConstructorStats::get()"); diff --git a/tests/test_eigen_tensor.inl b/tests/test_eigen_tensor.inl index 25cf29f1..3b3641e8 100644 --- a/tests/test_eigen_tensor.inl +++ b/tests/test_eigen_tensor.inl @@ -147,33 +147,39 @@ void init_tensor_module(pybind11::module &m) { m.def( "take_fixed_tensor", - []() { Eigen::aligned_allocator< Eigen::TensorFixedSize, Options>> allocator; - return new (allocator.allocate(1)) + static auto *obj = new (allocator.allocate(1)) Eigen::TensorFixedSize, Options>( get_fixed_tensor()); + return obj; // take_ownership will fail. }, py::return_value_policy::take_ownership); m.def( "take_tensor", - []() { return new Eigen::Tensor(get_tensor()); }, + []() { + static auto *obj = new Eigen::Tensor(get_tensor()); + return obj; // take_ownership will fail. + }, py::return_value_policy::take_ownership); m.def( "take_const_tensor", []() -> const Eigen::Tensor * { - return new Eigen::Tensor(get_tensor()); + static auto *obj = new Eigen::Tensor(get_tensor()); + return obj; // take_ownership will fail. }, py::return_value_policy::take_ownership); m.def( "take_view_tensor", []() -> const Eigen::TensorMap> * { - return new Eigen::TensorMap>(get_tensor()); + static auto *obj + = new Eigen::TensorMap>(get_tensor()); + return obj; // take_ownership will fail. }, py::return_value_policy::take_ownership); diff --git a/tests/test_modules.cpp b/tests/test_modules.cpp index 18a7ec74..7f01687c 100644 --- a/tests/test_modules.cpp +++ b/tests/test_modules.cpp @@ -90,32 +90,32 @@ TEST_SUBMODULE(modules, m) { try { py::class_(dm, "Dupe1"); failures.append("Dupe1 class"); - } catch (std::runtime_error &) { + } catch (std::runtime_error &) { // NOLINT(bugprone-empty-catch) } try { dm.def("Dupe1", []() { return Dupe1(); }); failures.append("Dupe1 function"); - } catch (std::runtime_error &) { + } catch (std::runtime_error &) { // NOLINT(bugprone-empty-catch) } try { py::class_(dm, "dupe1_factory"); failures.append("dupe1_factory"); - } catch (std::runtime_error &) { + } catch (std::runtime_error &) { // NOLINT(bugprone-empty-catch) } try { py::exception(dm, "Dupe2"); failures.append("Dupe2"); - } catch (std::runtime_error &) { + } catch (std::runtime_error &) { // NOLINT(bugprone-empty-catch) } try { dm.def("DupeException", []() { return 30; }); failures.append("DupeException1"); - } catch (std::runtime_error &) { + } catch (std::runtime_error &) { // NOLINT(bugprone-empty-catch) } try { py::class_(dm, "DupeException"); failures.append("DupeException2"); - } catch (std::runtime_error &) { + } catch (std::runtime_error &) { // NOLINT(bugprone-empty-catch) } return failures; diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index ed77ec02..596d9027 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -266,6 +266,8 @@ py::array_t test_array_ctors(int i) { return fill(arr_t(buf_ndim1_null)); case 44: return fill(py::array(buf_ndim1_null)); + default: + break; } return arr_t(); } diff --git a/tests/test_opaque_types.cpp b/tests/test_opaque_types.cpp index 0386dba0..154d0a8d 100644 --- a/tests/test_opaque_types.cpp +++ b/tests/test_opaque_types.cpp @@ -65,7 +65,7 @@ TEST_SUBMODULE(opaque_types, m) { m.def("return_unique_ptr", []() -> std::unique_ptr { auto *result = new StringList(); - result->push_back("some value"); + result->emplace_back("some value"); return std::unique_ptr(result); }); diff --git a/tests/test_tagbased_polymorphic.cpp b/tests/test_tagbased_polymorphic.cpp index 12ba6532..24b49021 100644 --- a/tests/test_tagbased_polymorphic.cpp +++ b/tests/test_tagbased_polymorphic.cpp @@ -74,6 +74,7 @@ std::vector> create_zoo() { // simulate some new type of Dog that the Python bindings // haven't been updated for; it should still be considered // a Dog, not just an Animal. + // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) ret.emplace_back(new Dog("Ginger", Dog::Kind(150))); ret.emplace_back(new Chihuahua("Hertzl")); From c46d1362555aee527011c994da3bb0fd727adba7 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 29 Jul 2024 11:19:22 -0700 Subject: [PATCH 3/5] Tracking ci.yml changes from master. --- .github/workflows/ci_sh_def.yml | 6 ++++ .github/workflows/ci_sh_def.yml.patch | 42 +++++++++++++-------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci_sh_def.yml b/.github/workflows/ci_sh_def.yml index fd11911d..f37f7516 100644 --- a/.github/workflows/ci_sh_def.yml +++ b/.github/workflows/ci_sh_def.yml @@ -358,6 +358,12 @@ jobs: - clang: 16 std: 20 container_suffix: "-bullseye" + - clang: 17 + std: 20 + container_suffix: "-bookworm" + - clang: 18 + std: 20 + container_suffix: "-bookworm" name: "🐍 3 • Clang ${{ matrix.clang }} • C++${{ matrix.std }} • x64" container: "silkeh/clang:${{ matrix.clang }}${{ matrix.container_suffix }}" diff --git a/.github/workflows/ci_sh_def.yml.patch b/.github/workflows/ci_sh_def.yml.patch index e6f5e57f..456ca736 100644 --- a/.github/workflows/ci_sh_def.yml.patch +++ b/.github/workflows/ci_sh_def.yml.patch @@ -1,5 +1,5 @@ ---- ci.yml 2024-07-01 20:26:45.034547517 -0700 -+++ ci_sh_def.yml 2024-07-01 20:27:32.110506039 -0700 +--- ci.yml 2024-07-29 11:18:11.967568957 -0700 ++++ ci_sh_def.yml 2024-07-29 11:18:42.087538968 -0700 @@ -1,4 +1,16 @@ -name: CI +# PLEASE KEEP THIS GROUP OF FILES IN SYNC AT ALL TIMES: @@ -67,7 +67,7 @@ - name: Build run: cmake --build build -j 2 -@@ -358,6 +375,7 @@ +@@ -364,6 +381,7 @@ -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=${{ matrix.std }} @@ -75,7 +75,7 @@ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") - name: Build -@@ -387,7 +405,7 @@ +@@ -393,7 +411,7 @@ run: apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y cmake git python3-dev python3-pytest python3-numpy - name: Configure @@ -84,7 +84,7 @@ - name: Build run: cmake --build build -j2 --verbose -@@ -475,7 +493,7 @@ +@@ -481,7 +499,7 @@ cmake -S . -B build -DDOWNLOAD_CATCH=ON \ -DCMAKE_CXX_STANDARD=17 \ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") \ @@ -93,7 +93,7 @@ -DPYBIND11_TEST_FILTER="test_smart_ptr.cpp" - name: Build -@@ -531,6 +549,7 @@ +@@ -537,6 +555,7 @@ -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=${{ matrix.std }} @@ -101,7 +101,7 @@ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") - name: Build -@@ -553,6 +572,7 @@ +@@ -559,6 +578,7 @@ -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=${{ matrix.std }} @@ -109,7 +109,7 @@ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") "-DPYBIND11_TEST_OVERRIDE=test_call_policies.cpp;test_gil_scoped.cpp;test_thread.cpp" -@@ -602,6 +622,7 @@ +@@ -608,6 +628,7 @@ -DDOWNLOAD_CATCH=ON \ -DDOWNLOAD_EIGEN=OFF \ -DCMAKE_CXX_STANDARD=11 \ @@ -117,7 +117,7 @@ -DCMAKE_CXX_COMPILER=$(which icpc) \ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") -@@ -634,6 +655,7 @@ +@@ -640,6 +661,7 @@ -DDOWNLOAD_CATCH=ON \ -DDOWNLOAD_EIGEN=OFF \ -DCMAKE_CXX_STANDARD=17 \ @@ -125,7 +125,7 @@ -DCMAKE_CXX_COMPILER=$(which icpc) \ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") -@@ -705,6 +727,7 @@ +@@ -711,6 +733,7 @@ -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_STANDARD=11 @@ -133,7 +133,7 @@ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") - name: Build -@@ -755,6 +778,7 @@ +@@ -761,6 +784,7 @@ cmake ../pybind11-tests -DDOWNLOAD_CATCH=ON -DPYBIND11_WERROR=ON @@ -141,7 +141,7 @@ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") working-directory: /build-tests -@@ -858,6 +882,7 @@ +@@ -864,6 +888,7 @@ -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON @@ -149,7 +149,7 @@ ${{ matrix.args }} - name: Build C++11 run: cmake --build build -j 2 -@@ -912,6 +937,7 @@ +@@ -918,6 +943,7 @@ -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON @@ -157,7 +157,7 @@ ${{ matrix.args }} - name: Build C++11 run: cmake --build build --config Debug -j 2 -@@ -954,6 +980,7 @@ +@@ -960,6 +986,7 @@ -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_STANDARD=20 @@ -165,7 +165,7 @@ - name: Build C++20 run: cmake --build build -j 2 -@@ -974,6 +1001,7 @@ +@@ -980,6 +1007,7 @@ -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_STANDARD=20 @@ -173,7 +173,7 @@ "-DPYBIND11_TEST_OVERRIDE=test_call_policies.cpp;test_gil_scoped.cpp;test_thread.cpp" - name: Build C++20 - Exercise cmake -DPYBIND11_TEST_OVERRIDE -@@ -1026,6 +1054,7 @@ +@@ -1032,6 +1060,7 @@ run: >- cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=11 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") @@ -181,7 +181,7 @@ -S . -B build - name: Build C++11 -@@ -1047,6 +1076,7 @@ +@@ -1053,6 +1082,7 @@ run: >- cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=14 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") @@ -189,7 +189,7 @@ -S . -B build2 - name: Build C++14 -@@ -1068,6 +1098,7 @@ +@@ -1074,6 +1104,7 @@ run: >- cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=17 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") @@ -197,7 +197,7 @@ -S . -B build3 - name: Build C++17 -@@ -1135,6 +1166,7 @@ +@@ -1141,6 +1172,7 @@ -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_STANDARD=17 @@ -205,7 +205,7 @@ - name: Build run: cmake --build . -j 2 -@@ -1200,6 +1232,7 @@ +@@ -1206,6 +1238,7 @@ -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_STANDARD=17 @@ -213,7 +213,7 @@ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") - name: Build -@@ -1223,6 +1256,7 @@ +@@ -1229,6 +1262,7 @@ -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_STANDARD=17 From 79fd12b8ccb8cc9c0ab45162529cf2510730e4ec Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 29 Jul 2024 19:30:51 -0700 Subject: [PATCH 4/5] Add `NOLINTNEXTLINE(bugprone-unused-return-value)` in smart_holder_poc_test.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-on to https://github.com/pybind/pybind11/pull/5272 — clang-tidy upgrade (to version 18) Fixes this error: ``` /__w/pybind11/pybind11/tests/pure_cpp/smart_holder_poc_test.cpp:167:12: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [bugprone-unused-return-value,-warnings-as-errors] 167 | (void) new_owner.release(); // Manually verified: without this, clang++ -fsanitize=address | ^~~~~~~~~~~~~~~~~~~ ``` See also: https://clang.llvm.org/extra/clang-tidy/checks/bugprone/unused-return-value.html Specifically there: > std::unique_ptr::release(). Not using the return value can lead to resource leaks if the same pointer isn’t stored anywhere else. Often, ignoring the release() return value indicates that the programmer confused the function with reset(). I.e. the only way to tell clang-tidy that the smart_holder_poc_test.cpp is correct is to add the `NOLINT`. --- tests/pure_cpp/smart_holder_poc_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pure_cpp/smart_holder_poc_test.cpp b/tests/pure_cpp/smart_holder_poc_test.cpp index f820b9bf..a9ad0364 100644 --- a/tests/pure_cpp/smart_holder_poc_test.cpp +++ b/tests/pure_cpp/smart_holder_poc_test.cpp @@ -164,6 +164,7 @@ TEST_CASE("from_raw_ptr_take_ownership+disown+reclaim_disowned", "[S]") { REQUIRE(*new_owner == 19); hld.reclaim_disowned(); // Manually veriified: without this, clang++ -fsanitize=address reports // "detected memory leaks". + // NOLINTNEXTLINE(bugprone-unused-return-value) (void) new_owner.release(); // Manually verified: without this, clang++ -fsanitize=address // reports "attempting double-free". REQUIRE(hld.as_lvalue_ref() == 19); From 39be69a1e671f871e7e072fd82fb6393bb27e4da Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 29 Jul 2024 21:06:54 -0700 Subject: [PATCH 5/5] Updates related to clang-tidy upgrade (to version 18): https://github.com/pybind/pybind11/pull/5272 --- include/pybind11/detail/cross_extension_shared_state.h | 2 +- tests/test_class_sh_property_stl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pybind11/detail/cross_extension_shared_state.h b/include/pybind11/detail/cross_extension_shared_state.h index 3ce8adc2..69b6ad01 100644 --- a/include/pybind11/detail/cross_extension_shared_state.h +++ b/include/pybind11/detail/cross_extension_shared_state.h @@ -110,7 +110,7 @@ struct cross_extension_shared_state { } *payload_pp() = new payload_type(); get_python_state_dict()[AdapterType::abi_id()] - = capsule(payload_pp(), AdapterType::abi_id()); + = capsule(reinterpret_cast(payload_pp()), AdapterType::abi_id()); return **payload_pp(); } diff --git a/tests/test_class_sh_property_stl.cpp b/tests/test_class_sh_property_stl.cpp index 030a578d..39f02b52 100644 --- a/tests/test_class_sh_property_stl.cpp +++ b/tests/test_class_sh_property_stl.cpp @@ -20,7 +20,7 @@ struct FieldHolder { struct VectorFieldHolder { std::vector vec_fld_hld; - VectorFieldHolder() { vec_fld_hld.push_back(FieldHolder{Field{300}}); } + VectorFieldHolder() { vec_fld_hld.emplace_back(Field{300}); } void reset_at(std::size_t index, int wrapped_int) { if (index < vec_fld_hld.size()) { vec_fld_hld[index].fld.wrapped_int = wrapped_int;