From 4ded59ce7004ce66946aad4b3a2df28f0c7cfa5b Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Wed, 24 Mar 2021 02:42:33 +0100 Subject: [PATCH] launder aligned_storage pointers --- include/cubescript/cubescript.hh | 15 +++-- src/cs_std.hh | 5 +- src/cs_val.cc | 98 +++++++++++++++++--------------- 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index eecb728..635259d 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -11,6 +11,7 @@ #include #include #include +#include #include "cubescript_conf.hh" @@ -68,9 +69,9 @@ private: } virtual R operator()(A &&...args) { - return std::invoke( - *reinterpret_cast(&p_stor), std::forward(args)... - ); + return std::invoke(*std::launder( + reinterpret_cast(&p_stor) + ), std::forward(args)...); } private: @@ -114,7 +115,7 @@ private: } p_func->~base(); if (!small_storage()) { - auto &ad = *reinterpret_cast(&p_stor); + auto &ad = *std::launder(reinterpret_cast(&p_stor)); ad.af(ad.ud, p_func, ad.asize, 0); } } @@ -145,7 +146,7 @@ public: auto *p = static_cast(&p_stor); p_func = ::new (p) store{std::move(func)}; } else { - auto &ad = *reinterpret_cast(&p_stor); + auto &ad = *std::launder(reinterpret_cast(&p_stor)); ad.af = af; ad.ud = ud; ad.asize = sizeof(store); @@ -383,7 +384,9 @@ private: }; internal_state *get_state() const { - return reinterpret_cast const *>(&p_stor)->state; + return std::launder( + reinterpret_cast const *>(&p_stor) + )->state; } std::aligned_union_t<1, diff --git a/src/cs_std.hh b/src/cs_std.hh index e328f47..4dde671 100644 --- a/src/cs_std.hh +++ b/src/cs_std.hh @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -43,12 +44,12 @@ struct valarray { ~valarray() { for (std::size_t i = 0; i < N; ++i) { - reinterpret_cast(&stor[i])->~T(); + std::launder(reinterpret_cast(&stor[i]))->~T(); } } T &operator[](std::size_t i) { - return *reinterpret_cast(&stor[i]); + return *std::launder(reinterpret_cast(&stor[i])); } std::aligned_storage_t stor[N]; diff --git a/src/cs_val.cc b/src/cs_val.cc index a943163..6e85199 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -60,16 +60,18 @@ struct stor_priv_t { }; template -static inline T &csv_get(U &stor) { +static inline T &csv_get(U *stor) { /* ugly, but internal and unlikely to cause bugs */ - return const_cast(reinterpret_cast const &>(stor).val); + return const_cast(std::launder( + reinterpret_cast const *>(stor) + )->val); } template -static inline void csv_cleanup(value_type tv, T &stor) { +static inline void csv_cleanup(value_type tv, T *stor) { switch (tv) { case value_type::STRING: - reinterpret_cast(&stor)->~string_ref(); + std::launder(reinterpret_cast(stor))->~string_ref(); break; case value_type::CODE: { bcode_unref(csv_get(stor)); @@ -85,11 +87,11 @@ any_value::any_value(state &st): any_value(*st.p_state) {} any_value::any_value(internal_state &st): p_stor(), p_type(value_type::NONE) { - reinterpret_cast *>(&p_stor)->state = &st; + std::launder(reinterpret_cast *>(&p_stor))->state = &st; } any_value::~any_value() { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); } any_value::any_value(any_value const &v): any_value(*v.get_state()) { @@ -101,7 +103,7 @@ any_value::any_value(any_value &&v): any_value(*v.get_state()) { } any_value &any_value::operator=(any_value const &v) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); p_type = value_type::NONE; switch (v.get_type()) { case value_type::INT: @@ -113,7 +115,7 @@ any_value &any_value::operator=(any_value const &v) { case value_type::STRING: p_type = value_type::STRING; new (&p_stor) string_ref{ - *reinterpret_cast(&v.p_stor) + *std::launder(reinterpret_cast(&v.p_stor)) }; break; case value_type::CODE: @@ -136,45 +138,45 @@ value_type any_value::get_type() const { } void any_value::set_int(integer_type val) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); p_type = value_type::INT; - csv_get(p_stor) = val; + csv_get(&p_stor) = val; } void any_value::set_float(float_type val) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); p_type = value_type::FLOAT; - csv_get(p_stor) = val; + csv_get(&p_stor) = val; } void any_value::set_str(std::string_view val) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); new (&p_stor) string_ref{get_state(), val}; p_type = value_type::STRING; } void any_value::set_str(string_ref const &val) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); new (&p_stor) string_ref{val}; p_type = value_type::STRING; } void any_value::set_none() { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); p_type = value_type::NONE; } void any_value::set_code(bcode *val) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); p_type = value_type::CODE; bcode_addref(val->get_raw()); - csv_get(p_stor) = val; + csv_get(&p_stor) = val; } void any_value::set_ident(ident *val) { - csv_cleanup(p_type, p_stor); + csv_cleanup(p_type, &p_stor); p_type = value_type::IDENT; - csv_get(p_stor) = val; + csv_get(&p_stor) = val; } void any_value::force_none() { @@ -188,15 +190,15 @@ float_type any_value::force_float() { float_type rf = 0.0f; switch (get_type()) { case value_type::INT: - rf = csv_get(p_stor); + rf = csv_get(&p_stor); break; case value_type::STRING: rf = parse_float( - *reinterpret_cast(&p_stor) + *std::launder(reinterpret_cast(&p_stor)) ); break; case value_type::FLOAT: - return csv_get(p_stor); + return csv_get(&p_stor); default: break; } @@ -208,15 +210,15 @@ integer_type any_value::force_int() { integer_type ri = 0; switch (get_type()) { case value_type::FLOAT: - ri = csv_get(p_stor); + ri = csv_get(&p_stor); break; case value_type::STRING: ri = parse_int( - *reinterpret_cast(&p_stor) + *std::launder(reinterpret_cast(&p_stor)) ); break; case value_type::INT: - return csv_get(p_stor); + return csv_get(&p_stor); default: break; } @@ -229,30 +231,32 @@ std::string_view any_value::force_str() { std::string_view str; switch (get_type()) { case value_type::FLOAT: - str = floatstr(csv_get(p_stor), rs); + str = floatstr(csv_get(&p_stor), rs); break; case value_type::INT: - str = intstr(csv_get(p_stor), rs); + str = intstr(csv_get(&p_stor), rs); break; case value_type::STRING: - return *reinterpret_cast(&p_stor); + return *std::launder(reinterpret_cast(&p_stor)); default: str = rs.str(); break; } set_str(str); - return std::string_view(*reinterpret_cast(&p_stor)); + return std::string_view(*std::launder( + reinterpret_cast(&p_stor) + )); } integer_type any_value::get_int() const { switch (get_type()) { case value_type::FLOAT: - return integer_type(csv_get(p_stor)); + return integer_type(csv_get(&p_stor)); case value_type::INT: - return csv_get(p_stor); + return csv_get(&p_stor); case value_type::STRING: return parse_int( - *reinterpret_cast(&p_stor) + *std::launder(reinterpret_cast(&p_stor)) ); default: break; @@ -263,12 +267,12 @@ integer_type any_value::get_int() const { float_type any_value::get_float() const { switch (get_type()) { case value_type::FLOAT: - return csv_get(p_stor); + return csv_get(&p_stor); case value_type::INT: - return float_type(csv_get(p_stor)); + return float_type(csv_get(&p_stor)); case value_type::STRING: return parse_float( - *reinterpret_cast(&p_stor) + *std::launder(reinterpret_cast(&p_stor)) ); default: break; @@ -280,30 +284,30 @@ bcode *any_value::get_code() const { if (get_type() != value_type::CODE) { return nullptr; } - return csv_get(p_stor); + return csv_get(&p_stor); } ident *any_value::get_ident() const { if (get_type() != value_type::IDENT) { return nullptr; } - return csv_get(p_stor); + return csv_get(&p_stor); } string_ref any_value::get_str() const { switch (get_type()) { case value_type::STRING: - return *reinterpret_cast(&p_stor); + return *std::launder(reinterpret_cast(&p_stor)); case value_type::INT: { charbuf rs{get_state()}; return string_ref{ - get_state(), intstr(csv_get(p_stor), rs) + get_state(), intstr(csv_get(&p_stor), rs) }; } case value_type::FLOAT: { charbuf rs{get_state()}; return string_ref{ - get_state(), floatstr(csv_get(p_stor), rs) + get_state(), floatstr(csv_get(&p_stor), rs) }; } default: @@ -318,10 +322,10 @@ void any_value::get_val(any_value &r) const { r = *this; break; case value_type::INT: - r.set_int(csv_get(p_stor)); + r.set_int(csv_get(&p_stor)); break; case value_type::FLOAT: - r.set_float(csv_get(p_stor)); + r.set_float(csv_get(&p_stor)); break; default: r.set_none(); @@ -340,17 +344,19 @@ bool any_value::code_is_empty() const { if (get_type() != value_type::CODE) { return true; } - return cubescript::code_is_empty(csv_get(p_stor)); + return cubescript::code_is_empty(csv_get(&p_stor)); } bool any_value::get_bool() const { switch (get_type()) { case value_type::FLOAT: - return csv_get(p_stor) != 0; + return csv_get(&p_stor) != 0; case value_type::INT: - return csv_get(p_stor) != 0; + return csv_get(&p_stor) != 0; case value_type::STRING: { - std::string_view s = *reinterpret_cast(&p_stor); + std::string_view s = *std::launder( + reinterpret_cast(&p_stor) + ); if (s.empty()) { return false; }