Skip to content

Commit

Permalink
Workaround for LLVM-46269 constrained destructor ordering (#2630)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpplearner authored Apr 4, 2022
1 parent 2127ea0 commit e7f5b27
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 12 deletions.
7 changes: 3 additions & 4 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
15 changes: 7 additions & 8 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions tests/std/tests/P0896R4_common_iterator/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<non_trivially_destructible_input_iterator, default_sentinel_t> it;
}

int main() {
with_writable_iterators<instantiator, P>::call();
static_assert(with_writable_iterators<instantiator, P>::call());
Expand Down
32 changes: 32 additions & 0 deletions tests/std/tests/P0896R4_views_join/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<non_trivially_destructible_input_iterator, default_sentinel_t>;

auto r = views::empty<Inner> | views::join;
(void) r.begin();

// Also validate _Non_propagating_cache
auto r2 = views::empty<Inner> | views::transform([](Inner& r) { return r; }) | views::join;
}

int main() {
// Validate views
constexpr string_view expected = "Hello World!"sv;
Expand Down
14 changes: 14 additions & 0 deletions tests/std/tests/P0896R4_views_single/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ static_assert(same_as<ranges::single_view<const char*>, decltype(views::single("
void double_function(double);
static_assert(same_as<ranges::single_view<void (*)(double)>, 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);
Expand Down

0 comments on commit e7f5b27

Please sign in to comment.