From ed34b2febb63a4570eb973b8cfaea7ca02f671fb Mon Sep 17 00:00:00 2001 From: Mohamed Atef Date: Fri, 21 Feb 2025 21:17:25 +0200 Subject: [PATCH] [libcxx] Add LWG4135: The helper lambda of std::erase for list should specify return type as bool --- libcxx/docs/Status/Cxx2cIssues.csv | 2 +- libcxx/include/forward_list | 2 +- libcxx/include/list | 2 +- .../forwardlist/bool-conversion.pass.cpp | 37 +++++++++++++++++++ .../list.modifiers/bool-conversion.pass.cpp | 37 +++++++++++++++++++ 5 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 libcxx/test/libcxx/containers/sequences/forwardlist/bool-conversion.pass.cpp create mode 100644 libcxx/test/libcxx/containers/sequences/list/list.modifiers/bool-conversion.pass.cpp diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index 1ec23dfabd5ea..228d95dead807 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -97,7 +97,7 @@ "`LWG4124 `__","Cannot format ``zoned_time`` with resolution coarser than ``seconds``","2024-11 (Wrocław)","","","" "`LWG4126 `__","Some feature-test macros for fully freestanding features are not yet marked freestanding","2024-11 (Wrocław)","","","" "`LWG4134 `__","Issue with Philox algorithm specification","2024-11 (Wrocław)","","","" -"`LWG4135 `__","The helper lambda of ``std::erase`` for list should specify return type as ``bool``","2024-11 (Wrocław)","","","" +"`LWG4135 `__","The helper lambda of ``std::erase`` for list should specify return type as ``bool``","2024-11 (Wrocław)","|Complete|","21","" "`LWG4140 `__","Useless default constructors for bit reference types","2024-11 (Wrocław)","","","" "`LWG4141 `__","Improve prohibitions on ""additional storage""","2024-11 (Wrocław)","","","" "`LWG4142 `__","``format_parse_context::check_dynamic_spec`` should require at least one type","2024-11 (Wrocław)","","","" diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index 4b6ca8ea8587c..8c688611d5ee2 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -1557,7 +1557,7 @@ erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { template inline _LIBCPP_HIDE_FROM_ABI typename forward_list<_Tp, _Allocator>::size_type erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) { - return std::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); + return std::erase_if(__c, [&](const auto& __elem) -> bool { return __elem == __v; }); } # endif diff --git a/libcxx/include/list b/libcxx/include/list index 3fcf796ebc03d..1285174f1c384 100644 --- a/libcxx/include/list +++ b/libcxx/include/list @@ -1703,7 +1703,7 @@ erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) { template inline _LIBCPP_HIDE_FROM_ABI typename list<_Tp, _Allocator>::size_type erase(list<_Tp, _Allocator>& __c, const _Up& __v) { - return std::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); + return std::erase_if(__c, [&](const auto& __elem) -> bool { return __elem == __v; }); } template <> diff --git a/libcxx/test/libcxx/containers/sequences/forwardlist/bool-conversion.pass.cpp b/libcxx/test/libcxx/containers/sequences/forwardlist/bool-conversion.pass.cpp new file mode 100644 index 0000000000000..237b0f155c7be --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/forwardlist/bool-conversion.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++20 + +// + +// This test shows the effect of implementing `LWG4135`, before it this code +// was ill-formed, as the predicate is not bool. `LWG4135` suggests that +// std::erase explicitly specifying the lambda's return type as bool. + +#include + +struct Bool { + Bool() = default; + Bool(const Bool&) = delete; + operator bool() const { return true; } +}; + +struct Int { + Bool& operator==(Int) const { + static Bool b; + return b; + } +}; + +int main(int, char**) { + std::forward_list l; + std::erase(l, Int{}); + + return 0; +} diff --git a/libcxx/test/libcxx/containers/sequences/list/list.modifiers/bool-conversion.pass.cpp b/libcxx/test/libcxx/containers/sequences/list/list.modifiers/bool-conversion.pass.cpp new file mode 100644 index 0000000000000..59083b8f45924 --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/list/list.modifiers/bool-conversion.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++20 + +// + +// This test shows the effect of implementing `LWG4135`, before it this code +// was ill-formed, as the predicate is not bool. `LWG4135` suggests that +// std::erase explicitly specifying the lambda's return type as bool. + +#include + +struct Bool { + Bool() = default; + Bool(const Bool&) = delete; + operator bool() const { return true; } +}; + +struct Int { + Bool& operator==(Int) const { + static Bool b; + return b; + } +}; + +int main(int, char**) { + std::list l; + std::erase(l, Int{}); + + return 0; +}