Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfixes for <any> #3965

Merged
merged 23 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is combining unrelated fixes, which makes things harder to review and harder to investigate/revert when things go wrong. They're small enough that I don't think we need to request changes, but I wanted to mention this for the future.

In general, I would say that combining unrelated cleanups is less risky than combining fixes; we want to avoid grab-bag PRs either way, but when semantic changes are involved, we should be more disciplined.

}

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 @@ -168,8 +168,10 @@ public:
}

any& operator=(any&& _That) noexcept {
reset();
_Move_from(_That);
if (this != &_That) {
reset();
_Move_from(_That);
}
achabense marked this conversation as resolved.
Show resolved Hide resolved
return *this;
}

Expand Down Expand Up @@ -295,14 +297,14 @@ private:
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
4 changes: 4 additions & 0 deletions tests/std/tests/GH_003965_robust_against_adl_any/env.lst
achabense marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_17_matrix.lst
37 changes: 37 additions & 0 deletions tests/std/tests/GH_003965_robust_against_adl_any/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <any>
#include <utility>

struct incomplete;

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

struct nontrivial {
nontrivial() {}
~nontrivial() {}
};

int main() {
using foo = wrapper<incomplete>*;
struct bar {
foo p{};
nontrivial q{};
};
struct baz {
foo p[20]{};
};

std::any a{foo{}}, b(bar{}), c{baz{}};
a = a, b = b, c = c;
a = std::move(a), b = std::move(b), c = std::move(c);
auto a_ = std::any_cast<foo>(a);
auto b_ = std::any_cast<bar>(b);
auto c_ = std::any_cast<baz>(c);

return 0;
}
18 changes: 18 additions & 0 deletions tests/std/tests/P0220R1_any/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3160,6 +3160,23 @@ namespace msvc {
}
#pragma warning(pop)
} // namespace trivial

namespace self_move_assign {
struct foo {
int val;
foo() : val(42) {}
~foo() {
val = 0;
}
};
void run_test() {
any a(foo{});
a = std::move(a);
assert(a.has_value());
assert(containsType<foo>(a));
assert(any_cast<foo>(&a)->val == 42);
}
} // namespace self_move_assign
} // namespace msvc

int main() {
Expand Down Expand Up @@ -3196,4 +3213,5 @@ int main() {
msvc::size_and_alignment::run_test();
msvc::small_type::run_test();
msvc::trivial::run_test();
msvc::self_move_assign::run_test();
}