Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
29 changes: 21 additions & 8 deletions stl/inc/flat_set
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ struct _NODISCARD _Flat_set_swap_clear_guard<true, _Container> {
void _Dismiss() noexcept {}
};

template <class _Container, class _Ty>
_NODISCARD auto _Emplace_with_clear_guard(_Container& _Cont, typename _Container::const_iterator _Where, _Ty&& _Val) {
if constexpr (_Has_guaranteed_single_insertion<_Container>) {
return _Cont.emplace(_Where, _STD forward<_Ty>(_Val));
} else {
_Clear_guard _Guard{_STD addressof(_Cont)};
auto _Iter = _Cont.emplace(_Where, _STD forward<_Ty>(_Val));
_Guard._Target = nullptr;
return _Iter;
}
}

_EXPORT_STD template <class _Kty, class _Keylt = less<_Kty>, class _Container = vector<_Kty>>
class flat_set;

Expand Down Expand Up @@ -279,8 +291,6 @@ public:
}

// modifiers
// FIXME, the "insert" and "erase" methods may not be able to restore the invariant, if the underlying
// container is unable to provide strong guarantee for "erase" and "insert" methods.
template <class... _Args>
auto emplace(_Args&&... _Vals) {
constexpr bool _Is_key_type = _In_place_key_extract_set<_Kty, remove_cvref_t<_Args>...>::_Extractable;
Expand Down Expand Up @@ -361,6 +371,9 @@ public:
_Guard._Target = nullptr;
}

// FIXME, the "erase" member functions need clear guards to restore the invariant when the underlying
// container doesn't provide the strong guarantee for its "erase" member functions.

// NB: `erase(iterator)` is identical to `erase(const_iterator)`
iterator erase(const_iterator _Where) {
return _Mycont.erase(_Where);
Expand Down Expand Up @@ -516,7 +529,7 @@ private:

if constexpr (is_same_v<remove_cvref_t<_Ty>, _Kty>) {
_STL_INTERNAL_CHECK(_Can_insert(_Where, _Val));
return pair{_Mycont.emplace(_Where, _STD forward<_Ty>(_Val)), true};
return pair{_STD _Emplace_with_clear_guard(_Mycont, _Where, _STD forward<_Ty>(_Val)), true};
} else {
// heterogeneous insertion
// FIXME: The standard only requires `find(_Val) == find(_Keyval)` (per N4958 [flat.set.modifiers]/2),
Expand All @@ -526,11 +539,11 @@ private:
_STL_ASSERT(_Can_insert(_Where, _Keyval),
"The conversion from the heterogeneous key to key_type should "
"be consistent with the heterogeneous lookup!");
return pair{_Mycont.emplace(_Where, _STD move(_Keyval)), true};
return pair{_STD _Emplace_with_clear_guard(_Mycont, _Where, _STD move(_Keyval)), true};
}
} else {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<remove_cvref_t<_Ty>, _Kty>);
return _Mycont.emplace(upper_bound(_Val), _STD forward<_Ty>(_Val));
return _STD _Emplace_with_clear_guard(_Mycont, upper_bound(_Val), _STD forward<_Ty>(_Val));
}
}

Expand Down Expand Up @@ -560,7 +573,7 @@ private:

if constexpr (is_same_v<remove_cvref_t<_Ty>, _Kty>) {
_STL_INTERNAL_CHECK(_Can_insert(_Where, _Val));
return _Mycont.emplace(_Where, _STD forward<_Ty>(_Val));
return _STD _Emplace_with_clear_guard(_Mycont, _Where, _STD forward<_Ty>(_Val));
} else {
// heterogeneous insertion
// FIXME: The standard only requires `find(_Val) == find(_Keyval)` (per N4958 [flat.set.modifiers]/2),
Expand All @@ -570,7 +583,7 @@ private:
_STL_ASSERT(_Can_insert(_Where, _Keyval),
"The conversion from the heterogeneous key to key_type should "
"be consistent with the heterogeneous lookup!");
return _Mycont.emplace(_Where, _STD move(_Keyval));
return _STD _Emplace_with_clear_guard(_Mycont, _Where, _STD move(_Keyval));
}
} else {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<remove_cvref_t<_Ty>, _Kty>);
Expand All @@ -591,7 +604,7 @@ private:
_Where = _STD lower_bound(_Where, _End, _Val, _Pass_comp());
}

return _Mycont.emplace(_Where, _STD forward<_Ty>(_Val));
return _STD _Emplace_with_clear_guard(_Mycont, _Where, _STD forward<_Ty>(_Val));
}
}

Expand Down
8 changes: 6 additions & 2 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -2762,10 +2762,14 @@ namespace ranges {
} // namespace ranges

template <class>
constexpr bool _Has_guaranteed_push_back = false; // N5014 [sequence.reqmts]/104, /108; used by flat_(multi)map::insert.
constexpr bool _Has_guaranteed_push_back = false; // N5032 [sequence.reqmts]/104, /108; used by flat_(multi)map::insert.

// N5032 [container.reqmts]/66.1; used by various flat_(multi)set inserting functions.
template <class _Ty>
constexpr bool _Has_guaranteed_single_insertion = _Has_guaranteed_push_back<_Ty>;

template <class>
constexpr bool _Has_guaranteed_append_range = false; // N5014 [sequence.reqmts]/112; used by flat_(multi)set::insert.
constexpr bool _Has_guaranteed_append_range = false; // N5032 [sequence.reqmts]/112; used by flat_(multi)set::insert.
#endif // _HAS_CXX23

template <class _Elem, class _UTy>
Expand Down
11 changes: 2 additions & 9 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@ std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cp
std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp:0 FAIL
std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp:1 FAIL

# LLVM-140448: [libc++][test] flat_set std test uses EmplaceUnsafeContainer which is non-standard
std/containers/container.adaptors/flat.set/flat.set.modifiers/emplace_hint.pass.cpp FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/emplace.pass.cpp FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_cv.pass.cpp FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_iter_cv.pass.cpp FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_iter_rv.pass.cpp FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_rv.pass.cpp FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_transparent.pass.cpp FAIL

# LLVM-158302: Clang 20 i686-pc-windows-msvc regression, silent bad codegen for std::current_exception()
# SKIPPED because this is x86-specific.
std/language.support/support.exception/except.nested/assign.pass.cpp:2 SKIPPED
Expand Down Expand Up @@ -435,6 +426,8 @@ std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_iter_iter.p
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_iter_iter.pass.cpp:1 FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp:0 FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp:1 FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_transparent.pass.cpp:0 FAIL
std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_transparent.pass.cpp:1 FAIL
std/containers/container.adaptors/flat.set/flat.set.observers/comp.pass.cpp:0 FAIL
std/containers/container.adaptors/flat.set/flat.set.observers/comp.pass.cpp:1 FAIL
std/containers/container.adaptors/flat.set/flat.set.operations/contains_transparent.pass.cpp:0 FAIL
Expand Down