Skip to content

Commit

Permalink
ensure that expected has no tail padding
Browse files Browse the repository at this point in the history
  • Loading branch information
jiixyj committed Oct 15, 2023
1 parent 7b81fb5 commit 9228950
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
19 changes: 19 additions & 0 deletions libcxx/include/__expected/expected.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <__memory/addressof.h>
#include <__memory/construct_at.h>
#include <__type_traits/conjunction.h>
#include <__type_traits/datasizeof.h>
#include <__type_traits/disjunction.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_assignable.h>
Expand Down Expand Up @@ -948,8 +949,17 @@ class expected {
return __union_t<_Tp, _Err>(std::unexpect, std::move(__other.__union_.__unex_));
}

_LIBCPP_HIDE_FROM_ABI static constexpr auto __calculate_padding() {
struct __calc_expected {
_LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
bool __has_val_;
};
return sizeof(__calc_expected) - __libcpp_datasizeof<__calc_expected>::value;
}

_LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
bool __has_val_;
char __padding_[__calculate_padding()]{};
};

template <class _Tp, class _Err>
Expand Down Expand Up @@ -1545,8 +1555,17 @@ class expected<_Tp, _Err> {
return __union_t<_Err>(std::unexpect, std::move(__other.__union_.__unex_));
}

_LIBCPP_HIDE_FROM_ABI static constexpr auto __calculate_padding() {
struct __calc_expected {
_LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
bool __has_val_;
};
return sizeof(__calc_expected) - __libcpp_datasizeof<__calc_expected>::value;
}

_LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
bool __has_val_;
char __padding_[__calculate_padding()]{};
};

_LIBCPP_END_NAMESPACE_STD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ constexpr bool test() {
assert(e.value() == 10);
}

// Test that `expected` has no tail padding.
{
struct BoolWithPadding {
explicit operator bool() { return b; }

private:
alignas(4) bool b = false;
};

static_assert(sizeof(std::expected<BoolWithPadding, bool>) ==
std::__libcpp_datasizeof<std::expected<BoolWithPadding, bool>>::value);

static_assert(sizeof(std::expected<void, BoolWithPadding>) ==
std::__libcpp_datasizeof<std::expected<void, BoolWithPadding>>::value);
}

return true;
}

Expand Down

0 comments on commit 9228950

Please sign in to comment.