From 55d2fdee9a3e303ce08f66a564a3bf2d10e3fde4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivopalov Date: Wed, 8 Aug 2018 14:51:53 -0700 Subject: [PATCH] clustering_key_filter_ranges: Fix move assignment to avoid undefined behaviour. Get rid of the new(this) trick that results in undefined behaviour because the class contains a const reference member. Use std::reference_wrapper instead to ease the transition. Refs #3032. Signed-off-by: Vladimir Krivopalov Message-Id: <5642bf79659231627dd7f8693c17cb46f274bcda.1533765105.git.vladimir@scylladb.com> --- clustering_key_filter.hh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clustering_key_filter.hh b/clustering_key_filter.hh index 229f674748..7b672cf7d4 100644 --- a/clustering_key_filter.hh +++ b/clustering_key_filter.hh @@ -30,7 +30,7 @@ namespace query { class clustering_key_filter_ranges { clustering_row_ranges _storage; - const clustering_row_ranges& _ref; + std::reference_wrapper _ref; public: clustering_key_filter_ranges(const clustering_row_ranges& ranges) : _ref(ranges) { } struct reversed { }; @@ -39,21 +39,21 @@ public: clustering_key_filter_ranges(clustering_key_filter_ranges&& other) noexcept : _storage(std::move(other._storage)) - , _ref(&other._ref == &other._storage ? _storage : other._ref) + , _ref(&other._ref.get() == &other._storage ? _storage : other._ref.get()) { } clustering_key_filter_ranges& operator=(clustering_key_filter_ranges&& other) noexcept { if (this != &other) { - this->~clustering_key_filter_ranges(); - new (this) clustering_key_filter_ranges(std::move(other)); + _storage = std::move(other._storage); + _ref = (&other._ref.get() == &other._storage) ? _storage : other._ref.get(); } return *this; } - auto begin() const { return _ref.begin(); } - auto end() const { return _ref.end(); } - bool empty() const { return _ref.empty(); } - size_t size() const { return _ref.size(); } + auto begin() const { return _ref.get().begin(); } + auto end() const { return _ref.get().end(); } + bool empty() const { return _ref.get().empty(); } + size_t size() const { return _ref.get().size(); } const clustering_row_ranges& ranges() const { return _ref; } static clustering_key_filter_ranges get_ranges(const schema& schema, const query::partition_slice& slice, const partition_key& key) {