[libcxx-commits] [libcxx] [libc++][flat_multimap] Applied `[[nodiscard]]` (PR #169986)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Nov 29 02:46:36 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Hristo Hristov (H-G-Hristov)
<details>
<summary>Changes</summary>
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.htm
- https://wg21.link/map
---
Full diff: https://github.com/llvm/llvm-project/pull/169986.diff
2 Files Affected:
- (modified) libcxx/include/__flat_map/flat_multimap.h (+48-39)
- (modified) libcxx/test/libcxx/diagnostics/flat_multimap.nodiscard.verify.cpp (+87-7)
``````````diff
diff --git a/libcxx/include/__flat_map/flat_multimap.h b/libcxx/include/__flat_map/flat_multimap.h
index 6a608723da1ba..3db669066ba97 100644
--- a/libcxx/include/__flat_map/flat_multimap.h
+++ b/libcxx/include/__flat_map/flat_multimap.h
@@ -408,41 +408,45 @@ class flat_multimap {
}
// iterators
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept {
return iterator(__containers_.keys.begin(), __containers_.values.begin());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept {
return const_iterator(__containers_.keys.begin(), __containers_.values.begin());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept {
return iterator(__containers_.keys.end(), __containers_.values.end());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept {
return const_iterator(__containers_.keys.end(), __containers_.values.end());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept {
return reverse_iterator(end());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept {
return reverse_iterator(begin());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept {
+ return begin();
+ }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept {
+ return end();
+ }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(end());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(begin());
}
@@ -451,11 +455,11 @@ class flat_multimap {
return __containers_.keys.empty();
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept {
return __containers_.keys.size();
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept {
return std::min<size_type>(__containers_.keys.max_size(), __containers_.values.max_size());
}
@@ -578,7 +582,7 @@ class flat_multimap {
insert(sorted_equivalent, __il.begin(), __il.end());
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && {
auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
auto __ret = std::move(__containers_);
return __ret;
@@ -644,118 +648,123 @@ class flat_multimap {
}
// observers
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const {
return value_compare(__compare_);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept {
return __containers_.keys;
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type& values() const noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type&
+ values() const noexcept {
return __containers_.values;
}
// map operations
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) {
return __find_impl(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const {
return __find_impl(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) {
return __find_impl(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const {
return __find_impl(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const {
auto [__first, __last] = equal_range(__x);
return __last - __first;
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const {
auto [__first, __last] = equal_range(__x);
return __last - __first;
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const {
return find(__x) != end();
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const {
return find(__x) != end();
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) {
return __lower_bound<iterator>(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator
+ lower_bound(const key_type& __x) const {
return __lower_bound<const_iterator>(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) {
return __lower_bound<iterator>(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const {
return __lower_bound<const_iterator>(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) {
return __upper_bound<iterator>(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator
+ upper_bound(const key_type& __x) const {
return __upper_bound<const_iterator>(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) {
return __upper_bound<iterator>(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const {
return __upper_bound<const_iterator>(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const key_type& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator>
+ equal_range(const key_type& __x) {
return __equal_range_impl(*this, __x);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
equal_range(const key_type& __x) const {
return __equal_range_impl(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const _Kp& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator>
+ equal_range(const _Kp& __x) {
return __equal_range_impl(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
equal_range(const _Kp& __x) const {
return __equal_range_impl(*this, __x);
}
diff --git a/libcxx/test/libcxx/diagnostics/flat_multimap.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/flat_multimap.nodiscard.verify.cpp
index 9b7b827c9bec8..66d6c99aed70c 100644
--- a/libcxx/test/libcxx/diagnostics/flat_multimap.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/flat_multimap.nodiscard.verify.cpp
@@ -6,17 +6,97 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// REQUIRES: std-at-least-c++23
// <flat_map>
-// class flat_multimap
-
-// [[nodiscard]] bool empty() const noexcept;
+// Check that functions are marked [[nodiscard]]
#include <flat_map>
+#include <utility>
+
+template <typename T>
+struct TransparentKey {
+ T t;
+
+ constexpr explicit operator T() const { return t; }
+};
+
+struct TransparentCompare {
+ using is_transparent = void; // This makes the comparator transparent
+
+ template <typename T>
+ constexpr bool operator()(const T& t, const TransparentKey<T>& transparent) const {
+ return t < transparent.t;
+ }
+
+ template <typename T>
+ constexpr bool operator()(const TransparentKey<T>& transparent, const T& t) const {
+ return transparent.t < t;
+ }
+
+ template <typename T>
+ constexpr bool operator()(const T& t1, const T& t2) const {
+ return t1 < t2;
+ }
+};
+
+void test() {
+ std::flat_multimap<int, int, TransparentCompare> mm;
+ const std::flat_multimap<int, int, TransparentCompare> cmm;
+
+ mm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ cmm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.key_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.value_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.keys(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.values(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ int key = 0;
+ TransparentKey<int> tkey;
+
+ mm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.count(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ mm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-void f() {
- std::flat_multimap<int, int> c;
- c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ mm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cmm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/169986
More information about the libcxx-commits
mailing list