The std::expected proposal has unnecessary instances of undefined behaviour

for operator->, operator*, and error(). Make these into assertion failures
(this still conforms to the proposal).

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2022-09-03 16:41:30 +01:00
parent 7472b0dbca
commit 4de0d85abf
3 changed files with 84 additions and 1 deletions

View File

@ -161,7 +161,7 @@ Copyright: 2006 Nemanja Trifunovic
License: Boost-Software-License-1.0
Files: depends/sources/tl-expected-*.tar.gz
Copyright: 2017-2021 Sy Brand <simonrbrand@gmail.com> (@TartanLlama)
Copyright: 2017-2021 Sy Brand <simonrbrand@gmail.com> (@TartanLlama), 2022 The Zcash developers
License: CC0-1.0
Comment: Other contributors are Simon Truscott (@bobbleclank), Kévin Alexandre Boissonneault (@KABoissonneault),
and Björn Fahller (@rollbear).

View File

@ -4,6 +4,11 @@ $(package)_download_path=https://github.com/TartanLlama/expected/archive
$(package)_download_file=96d547c03d2feab8db64c53c3744a9b4a7c8f2c5.tar.gz
$(package)_file_name=tl-expected-1.0.1.tar.gz
$(package)_sha256_hash=64901df1de9a5a3737b331d3e1de146fa6ffb997017368b322c08f45c51b90a7
$(package)_patches=remove-undefined-behaviour.diff
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/remove-undefined-behaviour.diff
endef
define $(package)_stage_cmds
mkdir $($(package)_staging_dir)$(host_prefix)/include && \

View File

@ -0,0 +1,78 @@
diff --recursive --unified tl-expected-1.0.1-orig/include/tl/expected.hpp tl-expected-1.0.1/include/tl/expected.hpp
--- tl-expected-1.0.1-orig/include/tl/expected.hpp 2022-08-30 20:10:13.269489852 +0100
+++ tl-expected-1.0.1/include/tl/expected.hpp 2022-08-30 20:17:35.744258828 +0100
@@ -24,6 +24,7 @@
#include <functional>
#include <type_traits>
#include <utility>
+#include <cassert>
#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
#define TL_EXPECTED_EXCEPTIONS_ENABLED
@@ -1862,27 +1863,37 @@
}
}
- constexpr const T *operator->() const { return valptr(); }
- TL_EXPECTED_11_CONSTEXPR T *operator->() { return valptr(); }
+ constexpr const T *operator->() const {
+ assert(has_value());
+ return valptr();
+ }
+ TL_EXPECTED_11_CONSTEXPR T *operator->() {
+ assert(has_value());
+ return valptr();
+ }
template <class U = T,
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
constexpr const U &operator*() const & {
+ assert(has_value());
return val();
}
template <class U = T,
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
TL_EXPECTED_11_CONSTEXPR U &operator*() & {
+ assert(has_value());
return val();
}
template <class U = T,
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
constexpr const U &&operator*() const && {
+ assert(has_value());
return std::move(val());
}
template <class U = T,
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
TL_EXPECTED_11_CONSTEXPR U &&operator*() && {
+ assert(has_value());
return std::move(val());
}
@@ -1918,10 +1929,22 @@
return std::move(val());
}
- constexpr const E &error() const & { return err().value(); }
- TL_EXPECTED_11_CONSTEXPR E &error() & { return err().value(); }
- constexpr const E &&error() const && { return std::move(err().value()); }
- TL_EXPECTED_11_CONSTEXPR E &&error() && { return std::move(err().value()); }
+ constexpr const E &error() const & {
+ assert(!has_value());
+ return err().value();
+ }
+ TL_EXPECTED_11_CONSTEXPR E &error() & {
+ assert(!has_value());
+ return err().value();
+ }
+ constexpr const E &&error() const && {
+ assert(!has_value());
+ return std::move(err().value());
+ }
+ TL_EXPECTED_11_CONSTEXPR E &&error() && {
+ assert(!has_value());
+ return std::move(err().value());
+ }
template <class U> constexpr T value_or(U &&v) const & {
static_assert(std::is_copy_constructible<T>::value &&