@@ -22,8 +22,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
2222PYBIND11_NOINLINE void foreign_exception_translator(std::exception_ptr p) {
2323 auto &interop_internals = get_interop_internals ();
2424 for (pymb_framework *fw : interop_internals.exc_frameworks ) {
25- if (fw->translate_exception (&p))
25+ if (fw->translate_exception (&p) != 0 ) {
2626 return ;
27+ }
2728 }
2829 std::rethrow_exception (p);
2930}
@@ -47,14 +48,14 @@ inline void import_foreign_binding(pymb_binding *binding, const std::type_info *
4748 // Caller must hold the internals lock
4849 auto &interop_internals = get_interop_internals ();
4950 interop_internals.imported_any = true ;
50- auto range = interop_internals.bindings . equal_range ( *cpptype) ;
51- for (auto it = range. first ; it != range. second ; ++it ) {
52- if (it-> second == binding) {
51+ auto &lst = interop_internals.bindings [ *cpptype] ;
52+ for (pymb_binding *existing : lst ) {
53+ if (existing == binding) {
5354 return ; // already imported
5455 }
5556 }
5657 ++interop_internals.bindings_update_count ;
57- interop_internals. bindings . emplace (*cpptype, binding);
58+ lst. append ( binding);
5859}
5960
6061// Callback functions for other frameworks to operate on our objects
@@ -77,14 +78,14 @@ inline void *interop_cb_from_python(pymb_binding *binding,
7778 = reinterpret_borrow<capsule>(pytype.attr (native_enum_info::attribute_name ()));
7879 auto *info = cap.get_pointer <native_enum_info>();
7980 auto value = handle (pyobj).attr (" value" );
80- uint64_t ival;
81+ uint64_t ival = 0 ;
8182 if (info->is_signed && handle (value) < int_ (0 )) {
8283 ival = (uint64_t ) cast<int64_t >(value);
8384 } else {
8485 ival = cast<uint64_t >(value);
8586 }
8687 bytes holder{reinterpret_cast <const char *>(&ival)
87- + PYBIND11_BIG_ENDIAN * (8 - info->size_bytes ),
88+ + PYBIND11_BIG_ENDIAN * size_t (8 - info->size_bytes ),
8889 info->size_bytes };
8990 keep_referenced (keep_referenced_ctx, holder.ptr ());
9091 return PyBytes_AsString (holder.ptr ());
@@ -198,7 +199,7 @@ inline PyObject *interop_cb_to_python(pymb_binding *binding,
198199 auto cap
199200 = reinterpret_borrow<capsule>(pytype.attr (native_enum_info::attribute_name ()));
200201 auto *info = cap.get_pointer <native_enum_info>();
201- uint64_t key;
202+ uint64_t key = 0 ;
202203 switch (info->size_bytes ) {
203204 case 1 :
204205 key = *(uint8_t *) cobj;
@@ -215,10 +216,11 @@ inline PyObject *interop_cb_to_python(pymb_binding *binding,
215216 default :
216217 return nullptr ;
217218 }
218- if (rvp_ == pymb_rv_policy_take_ownership)
219+ if (rvp_ == pymb_rv_policy_take_ownership) {
219220 ::operator delete (cobj);
221+ }
220222 if (info->is_signed ) {
221- int64_t ikey = (int64_t ) key;
223+ auto ikey = (int64_t ) key;
222224 if (info->size_bytes < 8 ) {
223225 // sign extend
224226 ikey <<= (64 - (info->size_bytes * 8 ));
@@ -275,7 +277,7 @@ inline PyObject *interop_cb_to_python(pymb_binding *binding,
275277 srcs.init_instance = init_instance_unregistered;
276278 }
277279 handle ret = type_caster_generic::cast (srcs, rvp, {}, copy_ctor, move_ctor);
278- feedback->is_new = srcs.is_new ;
280+ feedback->is_new = uint8_t ( srcs.is_new ) ;
279281 return ret.ptr ();
280282 } catch (...) {
281283 translate_exception (std::current_exception ());
@@ -309,7 +311,9 @@ inline int interop_cb_keep_alive(PyObject *nurse, void *payload, void (*cb)(void
309311 // Create a shared_ptr whose destruction will perform the action
310312 std::shared_ptr<void > owner (payload, cb_to_use);
311313 // Use the aliasing constructor to make its get() return the right thing
314+ // NB: this constructor accepts an rvalue reference only in C++20
312315 new (std::addressof (v_h.holder <std::shared_ptr<void >>()))
316+ // NOLINTNEXTLINE(performance-move-const-arg)
313317 std::shared_ptr<void >(std::move (owner), v_h.value_ptr ());
314318 v_h.set_holder_constructed ();
315319 success = true ;
@@ -403,13 +407,12 @@ inline int interop_cb_translate_exception(void *eptr) noexcept {
403407inline void interop_cb_remove_local_binding (pymb_binding *binding) noexcept {
404408 with_internals ([&](internals &) {
405409 auto &interop_internals = get_interop_internals ();
406- auto *cpptype = (const std::type_info *) binding->native_type ;
407- auto range = interop_internals.bindings .equal_range (*cpptype);
408- for ( auto it = range. first ; it != range. second ; ++it ) {
409- if (it-> second == binding) {
410- ++interop_internals. bindings_update_count ;
410+ const auto *cpptype = (const std::type_info *) binding->native_type ;
411+ auto it = interop_internals.bindings .find (*cpptype);
412+ if ( it != interop_internals. bindings . end () && it-> second . erase (binding) ) {
413+ ++interop_internals. bindings_update_count ;
414+ if (it-> second . empty ()) {
411415 interop_internals.bindings .erase (it);
412- return ;
413416 }
414417 }
415418 });
@@ -433,12 +436,11 @@ inline void interop_cb_remove_foreign_binding(pymb_binding *binding) noexcept {
433436 with_internals ([&](internals &) {
434437 auto &interop_internals = get_interop_internals ();
435438 auto remove_from_type = [&](const std::type_info *type) {
436- auto range = interop_internals.bindings .equal_range (*type);
437- for ( auto it = range. first ; it != range. second ; ++it ) {
438- if (it-> second == binding) {
439- ++interop_internals. bindings_update_count ;
439+ auto it = interop_internals.bindings .find (*type);
440+ if ( it != interop_internals. bindings . end () && it-> second . erase (binding) ) {
441+ ++interop_internals. bindings_update_count ;
442+ if (it-> second . empty ()) {
440443 interop_internals.bindings .erase (it);
441- break ;
442444 }
443445 }
444446 };
@@ -641,11 +643,10 @@ PYBIND11_NOINLINE void interop_enable_import_all() {
641643PYBIND11_NOINLINE void
642644export_for_interop (const std::type_info *cpptype, PyTypeObject *pytype, type_info *ti) {
643645 auto &interop_internals = get_interop_internals ();
644- auto range = interop_internals.bindings .equal_range (*cpptype);
645- for (auto it = range.first ; it != range.second ; ++it) {
646- if (it->second ->framework == interop_internals.self .get ()
647- && it->second ->pytype == pytype) {
648- return ; // already exported
646+ auto &lst = interop_internals.bindings [*cpptype];
647+ for (pymb_binding *existing : lst) {
648+ if (existing->framework == interop_internals.self .get () && existing->pytype == pytype) {
649+ return ; // already imported
649650 }
650651 }
651652
@@ -657,7 +658,7 @@ export_for_interop(const std::type_info *cpptype, PyTypeObject *pytype, type_inf
657658 binding->context = ti;
658659
659660 ++interop_internals.bindings_update_count ;
660- interop_internals. bindings . emplace (*cpptype, binding);
661+ lst. append ( binding);
661662 pymb_add_binding (binding, /* tp_finalize_will_remove */ 0 );
662663}
663664
@@ -688,7 +689,7 @@ PYBIND11_NOINLINE void interop_enable_export_all() {
688689 handle (entry.second ).attr (native_enum_info::attribute_name ()));
689690 auto *info = cap.get_pointer <native_enum_info>();
690691 detail::export_for_interop (info->cpptype , (PyTypeObject *) entry.second , nullptr );
691- } catch (error_already_set &) {
692+ } catch (error_already_set &) { // NOLINT(bugprone-empty-catch)
692693 // Ignore native enums without a __pybind11_enum__ capsule;
693694 // they might be from an older version of pybind11
694695 }
@@ -710,10 +711,11 @@ PYBIND11_NOINLINE void *try_foreign_bindings(const std::type_info *type,
710711 do {
711712 PYBIND11_LOCK_INTERNALS (internals);
712713 (void ) internals; // suppress unused warning on non-ft builds
713- auto range = interop_internals.bindings .equal_range (*type);
714- auto it = range.first ;
715- for (; it != range.second ; ++it) {
716- auto *binding = it->second ;
714+ auto it = interop_internals.bindings .find (*type);
715+ if (it == interop_internals.bindings .end ()) {
716+ return nullptr ;
717+ }
718+ for (pymb_binding *binding : it->second ) {
717719 if (binding->framework == interop_internals.self .get ()
718720 && (!binding->context
719721 || !is_local_to_other_module ((type_info *) binding->context ))) {
@@ -741,13 +743,13 @@ PYBIND11_NOINLINE void *try_foreign_bindings(const std::type_info *type,
741743 // was done within attempt(), or concurrently during attempt()
742744 // while we didn't hold the internals lock
743745 if (interop_internals.bindings_update_count != update_count) {
744- // Concurrent update occurred; retry
745- update_count = interop_internals.bindings_update_count ;
746+ // Concurrent update occurred; stop iterating
746747 break ;
747748 }
748749 }
749- if (it != range. second ) {
750+ if (interop_internals. bindings_update_count != update_count ) {
750751 // We broke out early due to a concurrent update. Retry from the top.
752+ update_count = interop_internals.bindings_update_count ;
751753 continue ;
752754 }
753755 return nullptr ;
@@ -775,7 +777,7 @@ inline void import_for_interop(handle pytype) {
775777 auto &interop_internals = detail::get_interop_internals ();
776778 interop_internals.initialize_if_needed ();
777779 detail::with_internals (
778- [&](detail::internals &) { detail::import_for_interop (std::move ( pytype) , cpptype); });
780+ [&](detail::internals &) { detail::import_for_interop (pytype, cpptype); });
779781}
780782
781783inline void export_for_interop (handle ty) {
@@ -806,7 +808,8 @@ inline void export_for_interop(handle ty) {
806808 if (ours) {
807809 return ;
808810 }
809- } catch (error_already_set &) {
811+ } catch (error_already_set &) { // NOLINT(bugprone-empty-catch)
812+ // Could be an older native enum without __pybind11_enum__ capsule
810813 }
811814 pybind11_fail (" pybind11::export_for_interop: not a "
812815 " pybind11 class or enum bound in this domain" );
0 commit comments