@@ -22,8 +22,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
22
22
PYBIND11_NOINLINE void foreign_exception_translator(std::exception_ptr p) {
23
23
auto &interop_internals = get_interop_internals ();
24
24
for (pymb_framework *fw : interop_internals.exc_frameworks ) {
25
- if (fw->translate_exception (&p))
25
+ if (fw->translate_exception (&p) != 0 ) {
26
26
return ;
27
+ }
27
28
}
28
29
std::rethrow_exception (p);
29
30
}
@@ -47,14 +48,14 @@ inline void import_foreign_binding(pymb_binding *binding, const std::type_info *
47
48
// Caller must hold the internals lock
48
49
auto &interop_internals = get_interop_internals ();
49
50
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) {
53
54
return ; // already imported
54
55
}
55
56
}
56
57
++interop_internals.bindings_update_count ;
57
- interop_internals. bindings . emplace (*cpptype, binding);
58
+ lst. append ( binding);
58
59
}
59
60
60
61
// Callback functions for other frameworks to operate on our objects
@@ -77,14 +78,14 @@ inline void *interop_cb_from_python(pymb_binding *binding,
77
78
= reinterpret_borrow<capsule>(pytype.attr (native_enum_info::attribute_name ()));
78
79
auto *info = cap.get_pointer <native_enum_info>();
79
80
auto value = handle (pyobj).attr (" value" );
80
- uint64_t ival;
81
+ uint64_t ival = 0 ;
81
82
if (info->is_signed && handle (value) < int_ (0 )) {
82
83
ival = (uint64_t ) cast<int64_t >(value);
83
84
} else {
84
85
ival = cast<uint64_t >(value);
85
86
}
86
87
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 ),
88
89
info->size_bytes };
89
90
keep_referenced (keep_referenced_ctx, holder.ptr ());
90
91
return PyBytes_AsString (holder.ptr ());
@@ -198,7 +199,7 @@ inline PyObject *interop_cb_to_python(pymb_binding *binding,
198
199
auto cap
199
200
= reinterpret_borrow<capsule>(pytype.attr (native_enum_info::attribute_name ()));
200
201
auto *info = cap.get_pointer <native_enum_info>();
201
- uint64_t key;
202
+ uint64_t key = 0 ;
202
203
switch (info->size_bytes ) {
203
204
case 1 :
204
205
key = *(uint8_t *) cobj;
@@ -215,10 +216,11 @@ inline PyObject *interop_cb_to_python(pymb_binding *binding,
215
216
default :
216
217
return nullptr ;
217
218
}
218
- if (rvp_ == pymb_rv_policy_take_ownership)
219
+ if (rvp_ == pymb_rv_policy_take_ownership) {
219
220
::operator delete (cobj);
221
+ }
220
222
if (info->is_signed ) {
221
- int64_t ikey = (int64_t ) key;
223
+ auto ikey = (int64_t ) key;
222
224
if (info->size_bytes < 8 ) {
223
225
// sign extend
224
226
ikey <<= (64 - (info->size_bytes * 8 ));
@@ -275,7 +277,7 @@ inline PyObject *interop_cb_to_python(pymb_binding *binding,
275
277
srcs.init_instance = init_instance_unregistered;
276
278
}
277
279
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 ) ;
279
281
return ret.ptr ();
280
282
} catch (...) {
281
283
translate_exception (std::current_exception ());
@@ -309,7 +311,9 @@ inline int interop_cb_keep_alive(PyObject *nurse, void *payload, void (*cb)(void
309
311
// Create a shared_ptr whose destruction will perform the action
310
312
std::shared_ptr<void > owner (payload, cb_to_use);
311
313
// Use the aliasing constructor to make its get() return the right thing
314
+ // NB: this constructor accepts an rvalue reference only in C++20
312
315
new (std::addressof (v_h.holder <std::shared_ptr<void >>()))
316
+ // NOLINTNEXTLINE(performance-move-const-arg)
313
317
std::shared_ptr<void >(std::move (owner), v_h.value_ptr ());
314
318
v_h.set_holder_constructed ();
315
319
success = true ;
@@ -403,13 +407,12 @@ inline int interop_cb_translate_exception(void *eptr) noexcept {
403
407
inline void interop_cb_remove_local_binding (pymb_binding *binding) noexcept {
404
408
with_internals ([&](internals &) {
405
409
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 ()) {
411
415
interop_internals.bindings .erase (it);
412
- return ;
413
416
}
414
417
}
415
418
});
@@ -433,12 +436,11 @@ inline void interop_cb_remove_foreign_binding(pymb_binding *binding) noexcept {
433
436
with_internals ([&](internals &) {
434
437
auto &interop_internals = get_interop_internals ();
435
438
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 ()) {
440
443
interop_internals.bindings .erase (it);
441
- break ;
442
444
}
443
445
}
444
446
};
@@ -641,11 +643,10 @@ PYBIND11_NOINLINE void interop_enable_import_all() {
641
643
PYBIND11_NOINLINE void
642
644
export_for_interop (const std::type_info *cpptype, PyTypeObject *pytype, type_info *ti) {
643
645
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
649
650
}
650
651
}
651
652
@@ -657,7 +658,7 @@ export_for_interop(const std::type_info *cpptype, PyTypeObject *pytype, type_inf
657
658
binding->context = ti;
658
659
659
660
++interop_internals.bindings_update_count ;
660
- interop_internals. bindings . emplace (*cpptype, binding);
661
+ lst. append ( binding);
661
662
pymb_add_binding (binding, /* tp_finalize_will_remove */ 0 );
662
663
}
663
664
@@ -688,7 +689,7 @@ PYBIND11_NOINLINE void interop_enable_export_all() {
688
689
handle (entry.second ).attr (native_enum_info::attribute_name ()));
689
690
auto *info = cap.get_pointer <native_enum_info>();
690
691
detail::export_for_interop (info->cpptype , (PyTypeObject *) entry.second , nullptr );
691
- } catch (error_already_set &) {
692
+ } catch (error_already_set &) { // NOLINT(bugprone-empty-catch)
692
693
// Ignore native enums without a __pybind11_enum__ capsule;
693
694
// they might be from an older version of pybind11
694
695
}
@@ -710,10 +711,11 @@ PYBIND11_NOINLINE void *try_foreign_bindings(const std::type_info *type,
710
711
do {
711
712
PYBIND11_LOCK_INTERNALS (internals);
712
713
(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 ) {
717
719
if (binding->framework == interop_internals.self .get ()
718
720
&& (!binding->context
719
721
|| !is_local_to_other_module ((type_info *) binding->context ))) {
@@ -741,13 +743,13 @@ PYBIND11_NOINLINE void *try_foreign_bindings(const std::type_info *type,
741
743
// was done within attempt(), or concurrently during attempt()
742
744
// while we didn't hold the internals lock
743
745
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
746
747
break ;
747
748
}
748
749
}
749
- if (it != range. second ) {
750
+ if (interop_internals. bindings_update_count != update_count ) {
750
751
// We broke out early due to a concurrent update. Retry from the top.
752
+ update_count = interop_internals.bindings_update_count ;
751
753
continue ;
752
754
}
753
755
return nullptr ;
@@ -775,7 +777,7 @@ inline void import_for_interop(handle pytype) {
775
777
auto &interop_internals = detail::get_interop_internals ();
776
778
interop_internals.initialize_if_needed ();
777
779
detail::with_internals (
778
- [&](detail::internals &) { detail::import_for_interop (std::move ( pytype) , cpptype); });
780
+ [&](detail::internals &) { detail::import_for_interop (pytype, cpptype); });
779
781
}
780
782
781
783
inline void export_for_interop (handle ty) {
@@ -806,7 +808,8 @@ inline void export_for_interop(handle ty) {
806
808
if (ours) {
807
809
return ;
808
810
}
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
810
813
}
811
814
pybind11_fail (" pybind11::export_for_interop: not a "
812
815
" pybind11 class or enum bound in this domain" );
0 commit comments