[libcxx-commits] [libcxx] [libc++][multimap] Applied `[[nodiscard]]` (PR #171644)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Dec 10 08:49:01 PST 2025
https://github.com/H-G-Hristov created https://github.com/llvm/llvm-project/pull/171644
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.html
>From 75babad889e3f67c79920bd767111f52d3cdef3c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 10 Dec 2025 13:59:56 +0200
Subject: [PATCH 1/2] [libc++][multimap] Applied `[[nodiscard]]`
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.html
---
libcxx/include/map | 92 ++++++++-------
.../diagnostics/multimap.nodiscard.verify.cpp | 109 ++++++++++++++++++
2 files changed, 162 insertions(+), 39 deletions(-)
create mode 100644 libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp
diff --git a/libcxx/include/map b/libcxx/include/map
index 0dca11cabd12e..3d2b863b70823 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -1703,28 +1703,36 @@ public:
static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), "");
}
- _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
- _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
- _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
- _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
- _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
- _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); }
- _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
- _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT {
+ return const_reverse_iterator(end());
+ }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {
+ return const_reverse_iterator(begin());
+ }
- _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
- _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
- _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
- _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __tree_.size() == 0; }
- _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
- _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
- _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(__tree_.__alloc()); }
- _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); }
- _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__tree_.value_comp().key_comp()); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
+ return allocator_type(__tree_.__alloc());
+ }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const {
+ return value_compare(__tree_.value_comp().key_comp());
+ }
# ifndef _LIBCPP_CXX03_LANG
@@ -1794,10 +1802,10 @@ public:
"node_type with incompatible allocator passed to multimap::insert()");
return __tree_.template __node_handle_insert_multi<node_type>(__hint.__i_, std::move(__nh));
}
- _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
return __tree_.template __node_handle_extract<node_type>(__key);
}
- _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
}
template <class _Compare2>
@@ -1832,83 +1840,89 @@ public:
__tree_.swap(__m.__tree_);
}
- _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
- _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
return __tree_.find(__k);
}
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
return __tree_.find(__k);
}
# endif
- _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __tree_.__count_multi(__k); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const {
+ return __tree_.__count_multi(__k);
+ }
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
return __tree_.__count_multi(__k);
}
# endif
# if _LIBCPP_STD_VER >= 20
- _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
return find(__k) != end();
}
# endif // _LIBCPP_STD_VER >= 20
- _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_multi(__k); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) {
+ return __tree_.__lower_bound_multi(__k);
+ }
- _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
return __tree_.__lower_bound_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
return __tree_.__lower_bound_multi(__k);
}
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
return __tree_.__lower_bound_multi(__k);
}
# endif
- _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_multi(__k); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) {
+ return __tree_.__upper_bound_multi(__k);
+ }
- _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
return __tree_.__upper_bound_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
return __tree_.__upper_bound_multi(__k);
}
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
return __tree_.__upper_bound_multi(__k);
}
# endif
- _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
return __tree_.__equal_range_multi(__k);
}
- _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
return __tree_.__equal_range_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
return __tree_.__equal_range_multi(__k);
}
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
- _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
return __tree_.__equal_range_multi(__k);
}
# endif
diff --git a/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..7ac36e02cc9f7
--- /dev/null
+++ b/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Check that functions are marked [[nodiscard]]
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "test_macros.h"
+
+#if TEST_STD_VER >= 14
+struct TransparentKey {
+ explicit operator int() const;
+};
+
+struct TransparentCompare {
+ using is_transparent = void; // This makes the comparator transparent
+
+ bool operator()(const int&, const TransparentKey&) const;
+
+ bool operator()(const TransparentKey&, const int&) const;
+
+ bool operator()(const int&, const int&) const;
+};
+#endif // TEST_STD_VER >= 14
+
+void test() {
+ std::multimap<int, int> m;
+ const std::multimap<int, int> cm;
+
+ m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ m.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ cm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ m.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.key_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.value_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ int key = 0;
+
+#if TEST_STD_VER >= 17
+ m.extract(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ m.extract(m.cend()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+ m.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 14
+ std::map<int, int, TransparentCompare> tm;
+ const std::map<int, int, TransparentCompare> ctm{};
+
+ TransparentKey tkey;
+
+ tm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ctm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+ m.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 14
+ tm.count(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+#if TEST_STD_VER >= 20
+ m.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ tm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+ m.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 14
+ tm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ctm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+ m.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 14
+ tm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ctm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+ m.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ cm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 14
+ tm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ctm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+}
>From deaf1cb8283d265de882ae6c38b55d5c1e4692d1 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 10 Dec 2025 18:44:42 +0200
Subject: [PATCH 2/2] [libc++][multimap] Applied `[[nodiscard]]`
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.html
---
libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp
index 7ac36e02cc9f7..99e4fbceabf12 100644
--- a/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/multimap.nodiscard.verify.cpp
@@ -67,8 +67,8 @@ void test() {
m.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
#if TEST_STD_VER >= 14
- std::map<int, int, TransparentCompare> tm;
- const std::map<int, int, TransparentCompare> ctm{};
+ std::multimap<int, int, TransparentCompare> tm;
+ const std::multimap<int, int, TransparentCompare> ctm{};
TransparentKey tkey;
More information about the libcxx-commits
mailing list