From fa32cc8612e5fa841f6cd8ec4601bef8a522a6d8 Mon Sep 17 00:00:00 2001 From: Gene Hightower Date: Thu, 22 Oct 2026 10:18:32 -0700 Subject: [PATCH 1/5] Fil-c requires pointers stored in memory to be identifiable as pointers in the LLVM IR. --- include/boost/corosio/detail/ready_queue.hpp | 58 ++++++++++--------- include/boost/corosio/detail/scheduler_op.hpp | 2 +- .../detail/reactor/reactor_scheduler.hpp | 5 +- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/include/boost/corosio/detail/ready_queue.hpp b/include/boost/corosio/detail/ready_queue.hpp index 279588226..da6ca0f73 100644 --- a/include/boost/corosio/detail/ready_queue.hpp +++ b/include/boost/corosio/detail/ready_queue.hpp @@ -13,7 +13,6 @@ #include #include -#include #include namespace boost::corosio::detail { @@ -31,23 +30,25 @@ inline constexpr std::uintptr_t ready_cont_bit = 1; /// Return true if a queue entry refers to a continuation (vs a scheduler_op). inline bool -ready_is_continuation(std::uintptr_t e) noexcept +ready_is_continuation(void* e) noexcept { - return (e & ready_cont_bit) != 0; + return (reinterpret_cast(e) & ready_cont_bit) != 0; } /// Recover the scheduler_op from an op-tagged entry. inline scheduler_op* -ready_as_op(std::uintptr_t e) noexcept +ready_as_op(void* e) noexcept { - return std::bit_cast(e & ~ready_cont_bit); + return reinterpret_cast( + reinterpret_cast(e) & ~ready_cont_bit); } /// Recover the continuation from a continuation-tagged entry. inline capy::continuation* -ready_as_cont(std::uintptr_t e) noexcept +ready_as_cont(void* e) noexcept { - return std::bit_cast(e & ~ready_cont_bit); + return reinterpret_cast( + reinterpret_cast(e) & ~ready_cont_bit); } /** A unified intrusive FIFO of scheduler_ops and continuations. @@ -64,37 +65,36 @@ ready_as_cont(std::uintptr_t e) noexcept */ class ready_queue { - std::uintptr_t head_ = 0; // tagged first entry, 0 when empty - std::uintptr_t tail_ = 0; // tagged last entry, 0 when empty + void* head_ = nullptr; // tagged first entry, nullptr when empty + void* tail_ = nullptr; // tagged last entry, nullptr when empty // Read a node's next-link by value. A continuation's link lives in its - // void* `reserved` slot; bit_cast keeps us from forming a uintptr_t - // lvalue over that void* object (which would violate strict aliasing). + // void* `reserved` slot. // // GCC 12/13 false-positive: when inlining proves an entry refers to a // continuation, -Warray-bounds still diagnoses the untaken scheduler_op // branch against the smaller object. Fixed in GCC 14. BOOST_COROSIO_GCC_WARNING_PUSH BOOST_COROSIO_GCC_WARNING_DISABLE("-Warray-bounds") - static std::uintptr_t next_of(std::uintptr_t e) noexcept + static void* next_of(void* e) noexcept { if (ready_is_continuation(e)) - return std::bit_cast(ready_as_cont(e)->reserved); + return ready_as_cont(e)->reserved; return ready_as_op(e)->q_next_; } - static void set_next(std::uintptr_t e, std::uintptr_t nxt) noexcept + static void set_next(void* e, void* nxt) noexcept { if (ready_is_continuation(e)) - ready_as_cont(e)->reserved = std::bit_cast(nxt); + ready_as_cont(e)->reserved = nxt; else ready_as_op(e)->q_next_ = nxt; } BOOST_COROSIO_GCC_WARNING_POP - void push_entry(std::uintptr_t e) noexcept + void push_entry(void* e) noexcept { - set_next(e, 0); + set_next(e, nullptr); if (tail_) set_next(tail_, e); else @@ -107,8 +107,8 @@ class ready_queue ready_queue(ready_queue&& o) noexcept : head_(o.head_), tail_(o.tail_) { - o.head_ = 0; - o.tail_ = 0; + o.head_ = nullptr; + o.tail_ = nullptr; } ready_queue(ready_queue const&) = delete; @@ -118,19 +118,21 @@ class ready_queue /// Return true if the queue holds no entries. bool empty() const noexcept { - return head_ == 0; + return head_ == nullptr; } /// Append a scheduler_op to the back of the queue. void push(scheduler_op* op) noexcept { - push_entry(std::bit_cast(op)); + push_entry(reinterpret_cast(op)); } /// Append a continuation to the back of the queue. void push(capy::continuation& c) noexcept { - push_entry(std::bit_cast(&c) | ready_cont_bit); + push_entry( + reinterpret_cast( + reinterpret_cast(&c) | ready_cont_bit)); } /// Move all entries of @p other to the back in O(1); @p other is emptied. @@ -143,19 +145,19 @@ class ready_queue else head_ = other.head_; tail_ = other.tail_; - other.head_ = 0; - other.tail_ = 0; + other.head_ = nullptr; + other.tail_ = nullptr; } - /// Remove and return the front entry as a tagged value, or 0 when empty. - std::uintptr_t pop() noexcept + /// Remove and return the front entry as a tagged value, or nullptr when empty. + void* pop() noexcept { auto e = head_; if (!e) - return 0; + return nullptr; head_ = next_of(e); if (!head_) - tail_ = 0; + tail_ = nullptr; return e; } }; diff --git a/include/boost/corosio/detail/scheduler_op.hpp b/include/boost/corosio/detail/scheduler_op.hpp index 0bc72a7ea..0eb8ab08c 100644 --- a/include/boost/corosio/detail/scheduler_op.hpp +++ b/include/boost/corosio/detail/scheduler_op.hpp @@ -118,7 +118,7 @@ class scheduler_op : public intrusive_queue::node // the former 8-byte padding word, so size/alignment are unchanged. Used // only while this op is in the ready queue; node.next_ is used while it // is pending in an op_queue. An op is in one or the other, never both. - std::uintptr_t q_next_ = 0; + void* q_next_ = nullptr; }; using op_queue = intrusive_queue; diff --git a/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp b/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp index 148b28c02..685d955af 100644 --- a/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp +++ b/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp @@ -138,8 +138,7 @@ reactor_find_context(reactor_scheduler const* self) noexcept @par Thread Safety All public member functions are thread-safe. */ -class reactor_scheduler - : public scheduler +class reactor_scheduler : public scheduler { public: using context_type = reactor_scheduler_context; @@ -994,7 +993,7 @@ reactor_scheduler::do_one(lock_type& lock, long timeout_us, context_type& ctx) if (stopped_.load(std::memory_order_acquire)) return 0; - std::uintptr_t e = completed_ops_.pop(); + auto const e = completed_ops_.pop(); scheduler_op* op = ready_is_continuation(e) ? nullptr : ready_as_op(e); // Handle reactor sentinel — time to poll for I/O From e1c9a860971851a38e0bd89a4de61b0c4124a143 Mon Sep 17 00:00:00 2001 From: Gene Hightower Date: Thu, 22 Oct 2026 12:26:07 -0700 Subject: [PATCH 2/5] Use nullptr in place of 0, since we switched to void* from uintptr_t --- .../boost/corosio/native/detail/reactor/reactor_scheduler.hpp | 2 +- test/unit/ready_queue.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp b/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp index 685d955af..08d63a616 100644 --- a/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp +++ b/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp @@ -1037,7 +1037,7 @@ reactor_scheduler::do_one(lock_type& lock, long timeout_us, context_type& ctx) } // Handle ready entry (op or continuation) - if (e != 0) + if (e != nullptr) { bool more = !completed_ops_.empty(); diff --git a/test/unit/ready_queue.cpp b/test/unit/ready_queue.cpp index 7bad8780f..bef579eba 100644 --- a/test/unit/ready_queue.cpp +++ b/test/unit/ready_queue.cpp @@ -44,7 +44,7 @@ struct ready_queue_test auto e2 = q.pop(); BOOST_TEST(ready_as_op(e2) == &b); - BOOST_TEST(q.pop() == 0u); + BOOST_TEST(q.pop() == nullptr); BOOST_TEST(q.empty()); } @@ -80,7 +80,7 @@ struct ready_queue_test BOOST_TEST(q2.empty()); BOOST_TEST(ready_as_op(q1.pop()) == &a); BOOST_TEST(ready_as_op(q1.pop()) == &b); - BOOST_TEST(q1.pop() == 0u); + BOOST_TEST(q1.pop() == nullptr); } void run() From 8765ffae1874a0b8aff16d2148c9c1ee6fc2d708 Mon Sep 17 00:00:00 2001 From: Gene Hightower Date: Thu, 22 Oct 2026 12:32:18 -0700 Subject: [PATCH 3/5] Shush clang-tidy. --- include/boost/corosio/detail/ready_queue.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/boost/corosio/detail/ready_queue.hpp b/include/boost/corosio/detail/ready_queue.hpp index da6ca0f73..fc9d25cca 100644 --- a/include/boost/corosio/detail/ready_queue.hpp +++ b/include/boost/corosio/detail/ready_queue.hpp @@ -40,7 +40,8 @@ inline scheduler_op* ready_as_op(void* e) noexcept { return reinterpret_cast( - reinterpret_cast(e) & ~ready_cont_bit); + reinterpret_cast(e) & + ~ready_cont_bit); // NOLINT(performance-no-int-to-ptr) } /// Recover the continuation from a continuation-tagged entry. @@ -48,7 +49,8 @@ inline capy::continuation* ready_as_cont(void* e) noexcept { return reinterpret_cast( - reinterpret_cast(e) & ~ready_cont_bit); + reinterpret_cast(e) & + ~ready_cont_bit); // NOLINT(performance-no-int-to-ptr) } /** A unified intrusive FIFO of scheduler_ops and continuations. @@ -132,7 +134,8 @@ class ready_queue { push_entry( reinterpret_cast( - reinterpret_cast(&c) | ready_cont_bit)); + reinterpret_cast(&c) | + ready_cont_bit)); // NOLINT(performance-no-int-to-ptr) } /// Move all entries of @p other to the back in O(1); @p other is emptied. From dc072d73919d20db7b46eccca853cf5bcc2ff6ea Mon Sep 17 00:00:00 2001 From: Gene Hightower Date: Thu, 22 Oct 2026 13:41:17 -0700 Subject: [PATCH 4/5] Another try to shush clang-tidy. --- include/boost/corosio/detail/ready_queue.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/corosio/detail/ready_queue.hpp b/include/boost/corosio/detail/ready_queue.hpp index fc9d25cca..9740b1b20 100644 --- a/include/boost/corosio/detail/ready_queue.hpp +++ b/include/boost/corosio/detail/ready_queue.hpp @@ -39,18 +39,18 @@ ready_is_continuation(void* e) noexcept inline scheduler_op* ready_as_op(void* e) noexcept { + // NOLINTNEXTLINE(performance-no-int-to-ptr) return reinterpret_cast( - reinterpret_cast(e) & - ~ready_cont_bit); // NOLINT(performance-no-int-to-ptr) + reinterpret_cast(e) & ~ready_cont_bit); } /// Recover the continuation from a continuation-tagged entry. inline capy::continuation* ready_as_cont(void* e) noexcept { + // NOLINTNEXTLINE(performance-no-int-to-ptr) return reinterpret_cast( - reinterpret_cast(e) & - ~ready_cont_bit); // NOLINT(performance-no-int-to-ptr) + reinterpret_cast(e) & ~ready_cont_bit); } /** A unified intrusive FIFO of scheduler_ops and continuations. @@ -132,10 +132,10 @@ class ready_queue /// Append a continuation to the back of the queue. void push(capy::continuation& c) noexcept { + // NOLINTNEXTLINE(performance-no-int-to-ptr) push_entry( reinterpret_cast( - reinterpret_cast(&c) | - ready_cont_bit)); // NOLINT(performance-no-int-to-ptr) + reinterpret_cast(&c) | ready_cont_bit)); } /// Move all entries of @p other to the back in O(1); @p other is emptied. From a937bf75e005c7ad029e88a0e3b5e0400e03aec2 Mon Sep 17 00:00:00 2001 From: Gene Hightower Date: Thu, 22 Oct 2026 18:54:58 -0700 Subject: [PATCH 5/5] A line is very specific. --- include/boost/corosio/detail/ready_queue.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/corosio/detail/ready_queue.hpp b/include/boost/corosio/detail/ready_queue.hpp index 9740b1b20..bb3754c7d 100644 --- a/include/boost/corosio/detail/ready_queue.hpp +++ b/include/boost/corosio/detail/ready_queue.hpp @@ -132,8 +132,8 @@ class ready_queue /// Append a continuation to the back of the queue. void push(capy::continuation& c) noexcept { - // NOLINTNEXTLINE(performance-no-int-to-ptr) push_entry( + // NOLINTNEXTLINE(performance-no-int-to-ptr) reinterpret_cast( reinterpret_cast(&c) | ready_cont_bit)); }