Skip to content

Commit

Permalink
Bugfixes for <any> (#3965)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
achabense and StephanTLavavej authored Sep 21, 2023
1 parent ddebb7b commit 4047639
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 9 deletions.
22 changes: 13 additions & 9 deletions stl/inc/any
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,17 @@ struct _Any_small_RTTI { // Hand-rolled vtable for nontrivial types that can be

template <class _Ty>
static void __CLRCALL_PURE_OR_CDECL _Destroy_impl(void* const _Target) noexcept {
_Destroy_in_place(*static_cast<_Ty*>(_Target));
_STD _Destroy_in_place(*static_cast<_Ty*>(_Target));
}

template <class _Ty>
static void __CLRCALL_PURE_OR_CDECL _Copy_impl(void* const _Target, const void* const _Source) {
_Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast<const _Ty*>(_Source));
_STD _Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast<const _Ty*>(_Source));
}

template <class _Ty>
static void __CLRCALL_PURE_OR_CDECL _Move_impl(void* const _Target, void* const _Source) noexcept {
_Construct_in_place(*static_cast<_Ty*>(_Target), _STD move(*static_cast<_Ty*>(_Source)));
_STD _Construct_in_place(*static_cast<_Ty*>(_Target), _STD move(*static_cast<_Ty*>(_Source)));
}

_Destroy_fn* _Destroy;
Expand Down Expand Up @@ -163,13 +163,12 @@ public:

// Assignment [any.assign]
any& operator=(const any& _That) {
*this = any{_That};
_Assign(_That);
return *this;
}

any& operator=(any&& _That) noexcept {
reset();
_Move_from(_That);
_Assign(_STD move(_That));
return *this;
}

Expand All @@ -178,7 +177,7 @@ public:
int> = 0>
any& operator=(_ValueType&& _Value) {
// replace contained value with an object of type decay_t<_ValueType> initialized from _Value
*this = any{_STD forward<_ValueType>(_Value)};
_Assign(_STD forward<_ValueType>(_Value));
return *this;
}

Expand Down Expand Up @@ -290,19 +289,24 @@ private:
}
}

void _Assign(any _That) noexcept { // intentionally pass by value
reset();
_Move_from(_That);
}

template <class _Decayed, class... _Types>
_Decayed& _Emplace(_Types&&... _Args) { // emplace construct _Decayed
if constexpr (_Any_is_trivial<_Decayed>) {
// using the _Trivial representation
auto& _Obj = reinterpret_cast<_Decayed&>(_Storage._TrivialData);
_Construct_in_place(_Obj, _STD forward<_Types>(_Args)...);
_STD _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...);
_Storage._TypeData =
reinterpret_cast<uintptr_t>(&typeid(_Decayed)) | static_cast<uintptr_t>(_Any_representation::_Trivial);
return _Obj;
} else if constexpr (_Any_is_small<_Decayed>) {
// using the _Small representation
auto& _Obj = reinterpret_cast<_Decayed&>(_Storage._SmallStorage._Data);
_Construct_in_place(_Obj, _STD forward<_Types>(_Args)...);
_STD _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...);
_Storage._SmallStorage._RTTI = &_Any_small_RTTI_obj<_Decayed>;
_Storage._TypeData =
reinterpret_cast<uintptr_t>(&typeid(_Decayed)) | static_cast<uintptr_t>(_Any_representation::_Small);
Expand Down
57 changes: 57 additions & 0 deletions tests/std/tests/P0220R1_any/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2570,21 +2570,41 @@ namespace msvc {
// empty
any a;
a = std::move(a);
assertEmpty(a);

a = std::make_any<any>();
a = any_cast<any&&>(std::move(a)); // extract inner any
assertEmpty(a);
}
{
// small
any a{small{42}};
a = std::move(a);
assertContains<small>(a, 42);

a = std::make_any<any>(small{42});
a = any_cast<any&&>(std::move(a)); // extract inner any
assertContains<small>(a, 42);
}
{
// large
any a{large{42}};
a = std::move(a);
assertContains<large>(a, 42);

a = std::make_any<any>(large{42});
a = any_cast<any&&>(std::move(a)); // extract inner any
assertContains<large>(a, 42);
}
{
// trivial
any a{int{42}};
a = std::move(a);
assertContains<int>(a, 42);

a = std::make_any<any>(int{42});
a = any_cast<any&&>(std::move(a)); // extract inner any
assertContains<int>(a, 42);
}
}
#ifdef __clang__
Expand Down Expand Up @@ -3160,6 +3180,40 @@ namespace msvc {
}
#pragma warning(pop)
} // namespace trivial

#ifndef _M_CEE // TRANSITION, VSO-1659496
namespace gh_140_robust_against_adl {
struct incomplete;

template <class T>
struct wrapper {
T t;
};

template <class Type>
void test_for() {
any a;
a = any{Type()};
a = any{std::in_place_type<Type>};
a = Type();
a = std::make_any<Type>();
a.emplace<Type>();
assert(any_cast<Type>(&a) != nullptr);
}

void run_test() {
using _trivial = wrapper<incomplete>*;
using _small = std::pair<_trivial, small>;
using _large = std::pair<_trivial, large>;

globalMemCounter.disable_allocations = true;
test_for<_trivial>();
test_for<_small>();
globalMemCounter.disable_allocations = false;
test_for<_large>();
}
} // namespace gh_140_robust_against_adl
#endif // _M_CEE
} // namespace msvc

int main() {
Expand Down Expand Up @@ -3196,4 +3250,7 @@ int main() {
msvc::size_and_alignment::run_test();
msvc::small_type::run_test();
msvc::trivial::run_test();
#ifndef _M_CEE // TRANSITION, VSO-1659496
msvc::gh_140_robust_against_adl::run_test();
#endif // _M_CEE
}

0 comments on commit 4047639

Please sign in to comment.