From b9eb1d75d9715190d72dc6916232642337227e67 Mon Sep 17 00:00:00 2001 From: Damian Jarek Date: Thu, 22 Nov 2018 15:10:47 +0100 Subject: [PATCH] Fix buffers_cat uninitialized warning Signed-off-by: Damian Jarek --- CHANGELOG.md | 1 + include/boost/beast/core/impl/buffers_cat.ipp | 150 +++++++++--------- test/beast/core/buffers_cat.cpp | 11 ++ 3 files changed, 86 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 676ff6d3..7a322003 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Version 191: * Use lean_tuple in buffers_cat * Use lean_tuple in bind_handler, bind_front_handler * Use mp11 in detail::variant +* Fix buffers_cat uninitialized warning -------------------------------------------------------------------------------- diff --git a/include/boost/beast/core/impl/buffers_cat.ipp b/include/boost/beast/core/impl/buffers_cat.ipp index 1f50a96d..d1594574 100644 --- a/include/boost/beast/core/impl/buffers_cat.ipp +++ b/include/boost/beast/core/impl/buffers_cat.ipp @@ -24,23 +24,38 @@ namespace boost { namespace beast { -template -class buffers_cat_view::const_iterator -{ - // VFALCO The logic to skip empty sequences fails - // if there is just one buffer in the list. - static_assert(sizeof...(Bn) >= 2, - "A minimum of two sequences are required"); +namespace detail { +struct buffers_cat_view_iterator_base +{ struct past_end { char unused = 0; // make g++8 happy + boost::asio::mutable_buffer + operator*() const + { + BOOST_THROW_EXCEPTION(std::logic_error{ + "invalid iterator"}); + } + operator bool() const noexcept { return true; } }; +}; + +} // detail + +template +class buffers_cat_view::const_iterator + : private detail::buffers_cat_view_iterator_base +{ + // VFALCO The logic to skip empty sequences fails + // if there is just one buffer in the list. + static_assert(sizeof...(Bn) >= 2, + "A minimum of two sequences are required"); detail::lean_tuple const* bn_ = nullptr; detail::variant const& bn, bool at_end); - template - void - construct(C const&) - { - if(boost::asio::buffer_size( - detail::get(*bn_)) != 0) - { - it_.template emplace( - boost::asio::buffer_sequence_begin( - detail::get(*bn_))); - return; - } - construct(C{}); - } - - void - construct(C const&) - { - auto constexpr I = sizeof...(Bn)-1; - it_.template emplace( - boost::asio::buffer_sequence_begin( - detail::get(*bn_))); - } - - void - construct(C const&) - { - // end - auto constexpr I = sizeof...(Bn); - it_.template emplace(); - } - template void next(C const&) @@ -179,45 +162,54 @@ private: detail::get(*bn_))); } - template - reference - dereference(C const&) const + struct dereference { - if(it_.index() == I+1) - return *it_.template get(); - return dereference(C{}); - } + const_iterator const& self; - [[noreturn]] - reference - dereference(C const&) const - { - BOOST_THROW_EXCEPTION(std::logic_error{ - "invalid iterator"}); - } - - template - void - increment(C const&) - { - if(it_.index() == I+1) + [[noreturn]] + reference + operator()(mp11::mp_size_t<0>) { - if(++it_.template get() != - boost::asio::buffer_sequence_end( - detail::get(*bn_))) - return; - return next(C{}); + BOOST_THROW_EXCEPTION(std::logic_error{ + "invalid iterator"}); } - increment(C{}); - } - [[noreturn]] - void - increment(C const&) + template + reference operator()(I) + { + return *self.it_.template get(); + } + }; + + struct increment { - BOOST_THROW_EXCEPTION(std::logic_error{ - "invalid iterator"}); - } + const_iterator& self; + + [[noreturn]] + void + operator()(mp11::mp_size_t<0>) + { + BOOST_THROW_EXCEPTION(std::logic_error{ + "invalid iterator"}); + } + + [[noreturn]] + void + operator()(mp11::mp_size_t) + { + (*this)(mp11::mp_size_t<0>{}); + } + + template + void + operator()(mp11::mp_size_t) + { + auto& it = self.it_.template get(); + if (++it == boost::asio::buffer_sequence_end( + detail::get(*self.bn_))) + self.next(C()); + } + }; void decrement(C const&) @@ -272,9 +264,9 @@ const_iterator( : bn_(&bn) { if(! at_end) - construct(C<0>{}); + next(C<0>{}); else - construct(C{}); + next(C{}); } template @@ -306,7 +298,10 @@ const_iterator:: operator*() const -> reference { - return dereference(C<0>{}); + return mp11::mp_with_index< + sizeof...(Bn) + 2>( + it_.index(), + dereference{*this}); } template @@ -316,7 +311,10 @@ const_iterator:: operator++() -> const_iterator& { - increment(C<0>{}); + mp11::mp_with_index< + sizeof...(Bn) + 2>( + it_.index(), + increment{*this}); return *this; } diff --git a/test/beast/core/buffers_cat.cpp b/test/beast/core/buffers_cat.cpp index 582a3687..ca2ea93a 100644 --- a/test/beast/core/buffers_cat.cpp +++ b/test/beast/core/buffers_cat.cpp @@ -256,6 +256,16 @@ public: buffers_cat(buffers_prefix(i, buffers), cb)); } + void + test_empty_buffer_sequences() + { + using boost::asio::buffer_size; + using boost::asio::const_buffer; + std::vector v1; + std::vector v2; + BEAST_EXPECT(buffer_size(buffers_cat(v1, v2)) == 0); + } + void run() override { using boost::asio::const_buffer; @@ -301,6 +311,7 @@ public: testIterators(); testGccWarning1(); testGccWarning2(); + test_empty_buffer_sequences(); } };