diff --git a/stl/inc/iterator b/stl/inc/iterator index e4a2d53588..703e07eee2 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -618,15 +618,14 @@ public: } } - // clang-format off - constexpr ~_Variantish() requires is_trivially_destructible_v<_It> && is_trivially_destructible_v<_Se> = default; - // clang-format on - constexpr ~_Variantish() { _Raw_clear(); } + // TRANSITION, LLVM-46269, destructor order is significant // clang-format off + constexpr ~_Variantish() requires is_trivially_destructible_v<_It> && is_trivially_destructible_v<_Se> = default; + constexpr _Variantish& operator=(const _Variantish&) requires is_trivially_destructible_v<_It> && is_trivially_destructible_v<_Se> && is_trivially_copy_constructible_v<_It> diff --git a/stl/inc/ranges b/stl/inc/ranges index 821f873bd2..181ff5adb9 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -271,17 +271,16 @@ namespace ranges { is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _Val(_STD forward<_Types>(_Args)...), _Engaged{true} {} - // clang-format off - ~_Copyable_box() requires is_trivially_destructible_v<_Ty> = default; - // clang-format on - constexpr ~_Copyable_box() { if (_Engaged) { _Val.~_Ty(); } } + // TRANSITION, LLVM-46269, destructor order is significant // clang-format off + ~_Copyable_box() requires is_trivially_destructible_v<_Ty> = default; + _Copyable_box(const _Copyable_box&) requires is_trivially_copy_constructible_v<_Ty> = default; // clang-format on @@ -474,17 +473,16 @@ namespace ranges { public: constexpr _Defaultabox() noexcept {} - // clang-format off - ~_Defaultabox() requires is_trivially_destructible_v<_Ty> = default; - // clang-format on - constexpr ~_Defaultabox() { if (_Engaged) { _Val.~_Ty(); } } + // TRANSITION, LLVM-46269, destructor order is significant // clang-format off + ~_Defaultabox() requires is_trivially_destructible_v<_Ty> = default; + _Defaultabox(const _Defaultabox&) requires copy_constructible<_Ty> && is_trivially_copy_constructible_v<_Ty> = default; // clang-format on @@ -693,6 +691,7 @@ namespace ranges { } } + // TRANSITION, LLVM-46269, destructor order is significant // clang-format off ~_Non_propagating_cache() requires is_trivially_destructible_v<_Ty> = default; // clang-format on diff --git a/tests/std/tests/P0896R4_common_iterator/test.cpp b/tests/std/tests/P0896R4_common_iterator/test.cpp index b7faa6c7b4..a03779e514 100644 --- a/tests/std/tests/P0896R4_common_iterator/test.cpp +++ b/tests/std/tests/P0896R4_common_iterator/test.cpp @@ -311,6 +311,29 @@ constexpr bool test_lwg_3574() { return true; } +// Validate that _Variantish works when fed with a non-trivially-destructible type +void test_non_trivially_destructible_type() { // COMPILE-ONLY + struct non_trivially_destructible_input_iterator { + using difference_type = int; + using value_type = int; + + ~non_trivially_destructible_input_iterator() {} + + non_trivially_destructible_input_iterator& operator++() { + return *this; + } + void operator++(int) {} + int operator*() const { + return 0; + } + bool operator==(default_sentinel_t) const { + return true; + } + }; + + common_iterator it; +} + int main() { with_writable_iterators::call(); static_assert(with_writable_iterators::call()); diff --git a/tests/std/tests/P0896R4_views_join/test.cpp b/tests/std/tests/P0896R4_views_join/test.cpp index 4a90903015..a52dfed7e5 100644 --- a/tests/std/tests/P0896R4_views_join/test.cpp +++ b/tests/std/tests/P0896R4_views_join/test.cpp @@ -471,6 +471,38 @@ struct Immovable { Immovable& operator=(Immovable&&) = delete; }; +// Validate that the _Defaultabox primary template works when fed with a non-trivially-destructible type +void test_non_trivially_destructible_type() { // COMPILE-ONLY + struct non_trivially_destructible_input_iterator { + using difference_type = int; + using value_type = int; + + ~non_trivially_destructible_input_iterator() {} + + // To test the correct specialization of _Defaultabox, this type must not be default constructible. + non_trivially_destructible_input_iterator() = delete; + + non_trivially_destructible_input_iterator& operator++() { + return *this; + } + void operator++(int) {} + int operator*() const { + return 0; + } + bool operator==(default_sentinel_t) const { + return true; + } + }; + + using Inner = ranges::subrange; + + auto r = views::empty | views::join; + (void) r.begin(); + + // Also validate _Non_propagating_cache + auto r2 = views::empty | views::transform([](Inner& r) { return r; }) | views::join; +} + int main() { // Validate views constexpr string_view expected = "Hello World!"sv; diff --git a/tests/std/tests/P0896R4_views_single/test.cpp b/tests/std/tests/P0896R4_views_single/test.cpp index 8418926ab6..57438e12c0 100644 --- a/tests/std/tests/P0896R4_views_single/test.cpp +++ b/tests/std/tests/P0896R4_views_single/test.cpp @@ -139,6 +139,20 @@ static_assert(same_as, decltype(views::single(" void double_function(double); static_assert(same_as, decltype(views::single(double_function))>); +// Validate that the _Copyable_box primary template works when fed with a non-trivially-destructible type +void test_non_trivially_destructible_type() { // COMPILE-ONLY + struct non_trivially_destructible { + non_trivially_destructible() = default; + ~non_trivially_destructible() {} + + // To test the correct specialization of _Copyable_box, this type must not be copy assignable. + non_trivially_destructible(const non_trivially_destructible&) = default; + non_trivially_destructible& operator=(const non_trivially_destructible&) = delete; + }; + + (void) views::single(non_trivially_destructible{}); +} + int main() { static_assert(test_one_type(42, 42)); test_one_type(42, 42);