aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Voutilainen <ville.voutilainen@gmail.com>2019-03-26 15:00:05 +0000
committerVille Voutilainen <ville.voutilainen@gmail.com>2019-03-26 15:00:05 +0000
commit023a5856cb0aaf397ca4502a12702d41c9e3e608 (patch)
tree60ef3f98de7b5703ab6778a1ab26bb6b84d4c042
parent35df260d63e36fab8abd71d523f49896d6e9c3d9 (diff)
PR libstdc++/89825
Fix based on a suggestion by Antony Polukhin. * include/std/variant (_Extra_visit_slot_needed): New. (_Multi_array): Use it. (_S_apply_all_alts): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@269947 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog10
-rw-r--r--libstdc++-v3/include/std/variant29
2 files changed, 36 insertions, 3 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 62242607674..2e595b3eca8 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,15 @@
2019-03-26 Ville Voutilainen <ville.voutilainen@gmail.com>
+ PR libstdc++/89825
+ Fix based on a suggestion by Antony Polukhin.
+ * include/std/variant (__never_valueless): New.
+ (_M_valid): Use it.
+ (_Extra_visit_slot_needed): New.
+ (_Multi_array): Use it.
+ (_S_apply_all_alts): Likewise.
+
+2019-03-26 Ville Voutilainen <ville.voutilainen@gmail.com>
+
PR libstdc++/89824
Fix based on a suggestion by Antony Polukhin.
* include/std/variant (__gen_vtable): Don't reserve an
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 36314638e63..3932a8a0d14 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -323,6 +323,12 @@ namespace __variant
_Variadic_union<_Rest...> _M_rest;
};
+ template <typename... _Types>
+ constexpr bool __never_valueless()
+ {
+ return (is_trivially_copyable_v<_Types> && ...);
+ }
+
// Defines index and the dtor, possibly trivial.
template<bool __trivially_destructible, typename... _Types>
struct _Variant_storage;
@@ -408,7 +414,7 @@ namespace __variant
constexpr bool
_M_valid() const noexcept
{
- if constexpr ((is_trivially_copyable_v<_Types> && ...))
+ if constexpr (__never_valueless<_Types...>())
return true;
return this->_M_index != __index_type(variant_npos);
}
@@ -747,6 +753,20 @@ namespace __variant
void* __get_storage(_Variant&& __v)
{ return __v._M_storage(); }
+ template <typename _Maybe_variant_cookie, typename _Variant>
+ struct _Extra_visit_slot_needed
+ {
+ template <typename> struct _Variant_never_valueless;
+
+ template <typename... _Types>
+ struct _Variant_never_valueless<variant<_Types...>>
+ : bool_constant<__never_valueless<_Types...>()> {};
+
+ static constexpr bool value =
+ is_same_v<_Maybe_variant_cookie, __variant_cookie>
+ && !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value;
+ };
+
// Used for storing multi-dimensional vtable.
template<typename _Tp, size_t... _Dimensions>
struct _Multi_array
@@ -764,8 +784,11 @@ namespace __variant
size_t __first, size_t... __rest>
struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...>
{
+ static constexpr size_t __index =
+ sizeof...(_Variants) - sizeof...(__rest) - 1;
+ using _Variant = typename _Nth_type<__index, _Variants...>::type;
static constexpr int __do_cookie =
- is_same_v<_Ret, __variant_cookie> ? 1 : 0;
+ _Extra_visit_slot_needed<_Ret, _Variant>::value ? 1 : 0;
using _Tp = _Ret(*)(_Visitor, _Variants...);
template<typename... _Args>
constexpr const _Tp&
@@ -832,7 +855,7 @@ namespace __variant
_S_apply_all_alts(_Array_type& __vtable,
std::index_sequence<__var_indices...>)
{
- if constexpr (is_same_v<_Result_type, __variant_cookie>)
+ if constexpr (_Extra_visit_slot_needed<_Result_type, _Next>::value)
(_S_apply_single_alt<true, __var_indices>(
__vtable._M_arr[__var_indices + 1],
&(__vtable._M_arr[0])), ...);