From 6b97869652116ff5ef41578eff302393286e5c82 Mon Sep 17 00:00:00 2001 From: AnmolS05 Date: Mon, 5 Oct 2026 11:48:30 +0530 Subject: [PATCH] Suppress GCC false positive -Wstringop-overflow in enqueue_bulk (#456) GCC 14+ emits a spurious -Wstringop-overflow diagnostic under -O2/-O3 when enqueue_bulk is called with an explicit producer token and an iterator materializing move-only elements on dereference. Wrap the static_cast in inner_enqueue_bulk with a localized diagnostic pragma (guarded by __GNUC__ >= 7) as endorsed in issue #456. Add a unit test verifying bulk enqueuing with an explicit producer token, move-only objects, and a generating iterator. --- CHANGELOG.md | 14 +++++++++ concurrentqueue.h | 7 +++++ tests/unittests/unittests.cpp | 53 +++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..8273d525 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +## [Unreleased] - 2026-10-05T11:47:00+05:30 + +### Fixed +- Suppressed spurious GCC `-Wstringop-overflow` diagnostic warning emitted under `-O2`/`-O3` optimization levels on GCC 14+ during `enqueue_bulk` with explicit producer tokens and dereferencing/generating iterators (Issue #456). +- Added `__GNUC__ >= 7` guarded localized diagnostic pragma to `ConcurrentQueue::inner_enqueue_bulk`. + +### Added +- Added unit test `enqueue_bulk_producer_token_generating_iterator` covering bulk enqueue operations with explicit producer tokens, move-only objects, and generating iterators. + +### Files Affected +- `concurrentqueue.h` +- `tests/unittests/unittests.cpp` diff --git a/concurrentqueue.h b/concurrentqueue.h index dcde4e6e..5dd7fdd5 100644 --- a/concurrentqueue.h +++ b/concurrentqueue.h @@ -1408,7 +1408,14 @@ class ConcurrentQueue template inline bool inner_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) { +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif return static_cast(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue_bulk(itemFirst, count); +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif } template diff --git a/tests/unittests/unittests.cpp b/tests/unittests/unittests.cpp index 7371f03e..db8a86d7 100644 --- a/tests/unittests/unittests.cpp +++ b/tests/unittests/unittests.cpp @@ -388,6 +388,7 @@ class ConcurrentQueueTests : public TestClass REGISTER_TEST(explicit_strings_threaded); REGISTER_TEST(large_traits); REGISTER_TEST(implicit_producer_index_limit); + REGISTER_TEST(enqueue_bulk_producer_token_generating_iterator); } bool postTest(bool testSucceeded) override @@ -5134,6 +5135,58 @@ class ConcurrentQueueTests : public TestClass return true; } + + /** + * @brief Verifies bulk enqueuing using an explicit producer token with a generating iterator + * and move-only types, validating avoidance of -Wstringop-overflow false positive (Issue #456). + * + * @return true if all assertions succeed. + */ + bool enqueue_bulk_producer_token_generating_iterator() + { + struct MoveOnlyTask { + int id; + alignas(16) char storage[48]; + MoveOnlyTask() : id(-1) { std::memset(storage, 0, sizeof(storage)); } + explicit MoveOnlyTask(int id) : id(id) { std::memset(storage, 0, sizeof(storage)); } + MoveOnlyTask(MoveOnlyTask&& o) MOODYCAMEL_NOEXCEPT : id(o.id) { + o.id = -1; + std::memcpy(storage, o.storage, sizeof(storage)); + } + MoveOnlyTask& operator=(MoveOnlyTask&& o) MOODYCAMEL_NOEXCEPT { + id = o.id; + o.id = -1; + std::memcpy(storage, o.storage, sizeof(storage)); + return *this; + } + MoveOnlyTask(const MoveOnlyTask&) MOODYCAMEL_DELETE_FUNCTION; + MoveOnlyTask& operator=(const MoveOnlyTask&) MOODYCAMEL_DELETE_FUNCTION; + }; + + struct GeneratorIterator { + int current; + MoveOnlyTask operator*() const { return MoveOnlyTask(current); } + GeneratorIterator& operator++() { ++current; return *this; } + GeneratorIterator operator++(int) { GeneratorIterator copy = *this; ++current; return copy; } + bool operator!=(const GeneratorIterator& o) const { return current != o.current; } + }; + + ConcurrentQueue q; + ProducerToken tok(q); + GeneratorIterator it{0}; + const size_t COUNT = 64; + ASSERT_OR_FAIL(q.enqueue_bulk(tok, it, COUNT)); + + for (size_t i = 0; i != COUNT; ++i) { + MoveOnlyTask task; + ASSERT_OR_FAIL(q.try_dequeue(task)); + ASSERT_OR_FAIL(task.id == static_cast(i)); + } + MoveOnlyTask extra; + ASSERT_OR_FAIL(!q.try_dequeue(extra)); + + return true; + } }; }