EricWF updated this revision to Diff 77769.
EricWF added a comment.
- Add `[[no_discard]]` to various smart pointer observers including `get()` and
`operator*()`.
https://reviews.llvm.org/D26596
Files:
docs/UsingLibcxx.rst
include/__config
include/__hash_table
include/__mutex_base
include/algorithm
include/deque
include/ext/hash_map
include/forward_list
include/list
include/locale
include/map
include/memory
include/mutex
include/regex
include/set
include/shared_mutex
include/string
include/string_view
include/thread
include/unordered_map
include/unordered_set
include/vector
test/libcxx/containers/no-discard-disable.fail.cpp
test/libcxx/containers/no-discard.fail.cpp
test/libcxx/test/config.py
test/libcxx/thread/thread.mutex/try_lock_no_discard.fail.cpp
test/libcxx/thread/thread.mutex/try_lock_no_discard_disabled.fail.cpp
test/libcxx/utilities/memory/disable_no_discard_smart_ptr_observers.fail.cpp
test/libcxx/utilities/memory/no_discard_smart_ptr_observers.fail.cpp
test/libcxx/utilities/memory/unique.ptr/disable_no_discard_release.fail.cpp
test/libcxx/utilities/memory/unique.ptr/no_discard_release.fail.cpp
test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp
test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp
test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp
test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
Index: test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
===================================================================
--- test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
+++ test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
@@ -48,7 +48,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_until(Clock::now());
+ (void)lk.try_lock_until(Clock::now());
assert(false);
}
catch (std::system_error& e)
@@ -64,7 +64,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_until(Clock::now());
+ (void)lk.try_lock_until(Clock::now());
assert(false);
}
catch (std::system_error& e)
Index: test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
===================================================================
--- test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
+++ test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
@@ -48,7 +48,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_for(ms(5));
+ (void)lk.try_lock_for(ms(5));
assert(false);
}
catch (std::system_error& e)
@@ -64,7 +64,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_for(ms(5));
+ (void)lk.try_lock_for(ms(5));
assert(false);
}
catch (std::system_error& e)
Index: test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
===================================================================
--- test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
+++ test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
@@ -43,7 +43,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock();
+ (void)lk.try_lock();
assert(false);
}
catch (std::system_error& e)
@@ -59,7 +59,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock();
+ (void)lk.try_lock();
assert(false);
}
catch (std::system_error& e)
Index: test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp
===================================================================
--- test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp
+++ test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp
@@ -49,7 +49,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_until(Clock::now());
+ (void)lk.try_lock_until(Clock::now());
assert(false);
}
catch (std::system_error& e)
@@ -65,7 +65,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_until(Clock::now());
+ (void)lk.try_lock_until(Clock::now());
assert(false);
}
catch (std::system_error& e)
Index: test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp
===================================================================
--- test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp
+++ test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp
@@ -49,7 +49,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_for(ms(5));
+ (void)lk.try_lock_for(ms(5));
assert(false);
}
catch (std::system_error& e)
@@ -65,7 +65,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock_for(ms(5));
+ (void)lk.try_lock_for(ms(5));
assert(false);
}
catch (std::system_error& e)
Index: test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp
===================================================================
--- test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp
+++ test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp
@@ -44,7 +44,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock();
+ (void)lk.try_lock();
assert(false);
}
catch (std::system_error& e)
@@ -60,7 +60,7 @@
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
- lk.try_lock();
+ (void)lk.try_lock();
assert(false);
}
catch (std::system_error& e)
Index: test/libcxx/utilities/memory/unique.ptr/no_discard_release.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/memory/unique.ptr/no_discard_release.fail.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-diagnostics
+
+// <memory>
+
+// unique_ptr
+
+// test [[no_discard]] warnings for release
+
+#include <memory>
+#include <cassert>
+
+int main()
+{
+ {
+ std::unique_ptr<int> p;
+ p.release(); // expected-warning {{ignoring return value}}
+ }
+ {
+ std::unique_ptr<int[]> p;
+ p.release(); // expected-warning {{ignoring return value}}
+ }
+}
Index: test/libcxx/utilities/memory/unique.ptr/disable_no_discard_release.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/memory/unique.ptr/disable_no_discard_release.fail.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-diagnostics
+
+// <memory>
+
+// unique_ptr
+
+// test [[no_discard]] warnings for release
+
+#define _LIBCPP_DISABLE_NO_DISCARD_UNIQUE_PTR_RELEASE
+#include <memory>
+#include <cassert>
+
+int main()
+{
+ // expected-no-diagnostics
+ {
+ std::unique_ptr<int> p;
+ p.release();
+ }
+ {
+ std::unique_ptr<int[]> p;
+ p.release();
+ }
+}
Index: test/libcxx/utilities/memory/no_discard_smart_ptr_observers.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/memory/no_discard_smart_ptr_observers.fail.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-diagnostics
+
+// <memory>
+
+// test the generated [[no_discard]] warnings for shared_ptr,
+// weak_ptr, and unique_ptr's observers.
+
+#include <memory>
+#include <cassert>
+
+int main()
+{
+ // shared_ptr
+ {
+ std::shared_ptr<int> p;
+ p.get(); // expected-warning {{ignoring return value}}
+ *p; // expected-warning {{ignoring return value}}
+ p.operator->(); // expected-warning {{ignoring return value}}
+ p.operator bool(); // expected-warning {{ignoring return value}}
+ p.use_count(); // expected-warning {{ignoring return value}}
+ p.unique(); // expected-warning {{ignoring return value}}
+ }
+ // weak_ptr
+ {
+ std::weak_ptr<int> p;
+ p.use_count(); // expected-warning {{ignoring return value}}
+ p.expired(); // expected-warning {{ignoring return value}}
+ }
+ // unique_ptr single
+ {
+ std::unique_ptr<int> p;
+ p.get(); // expected-warning {{ignoring return value}}
+ *p; // expected-warning {{ignoring return value}}
+ p.operator->(); // expected-warning {{ignoring return value}}
+ p.operator bool(); // expected-warning {{ignoring return value}}
+ }
+ // unique_ptr array
+ {
+ std::unique_ptr<int[]> p;
+ p.get(); // expected-warning {{ignoring return value}}
+ p[0]; // expected-warning {{ignoring return value}}
+ p.operator bool(); // expected-warning {{ignoring return value}}
+ }
+}
Index: test/libcxx/utilities/memory/disable_no_discard_smart_ptr_observers.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/memory/disable_no_discard_smart_ptr_observers.fail.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-diagnostics
+
+// <memory>
+
+// test the generated [[no_discard]] warnings for shared_ptr,
+// weak_ptr, and unique_ptr's observers.
+
+#define _LIBCPP_DISABLE_NO_DISCARD_SMART_PTR_OBSERVERS
+#include <memory>
+#include <cassert>
+
+int main()
+{
+ // expected-no-diagnostics
+ // shared_ptr
+ {
+ std::shared_ptr<int> p;
+ p.get();
+ *p;
+ p.operator->();
+ p.operator bool();
+ p.use_count();
+ p.unique();
+ }
+ // weak_ptr
+ {
+ std::weak_ptr<int> p;
+ p.use_count();
+ p.expired();
+ }
+ // unique_ptr single
+ {
+ std::unique_ptr<int> p;
+ p.get();
+ *p;
+ p.operator->();
+ p.operator bool();
+ }
+ // unique_ptr array
+ {
+ std::unique_ptr<int[]> p;
+ p.get();
+ p[0];
+ p.operator bool();
+ }
+}
Index: test/libcxx/thread/thread.mutex/try_lock_no_discard_disabled.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/thread/thread.mutex/try_lock_no_discard_disabled.fail.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: libcpp-has-no-threads
+// REQUIRES: verify-diagnostics
+
+// test the generated [[no_discard]] warnings
+
+#define _LIBCPP_DISABLE_NO_DISCARD_TRY_LOCK
+#include <mutex>
+#include <shared_mutex>
+
+#include "test_macros.h"
+
+int main() {
+ // expected-no-diagnostics
+ {
+ std::mutex m;
+ m.try_lock();
+ m.unlock();
+ }
+ {
+ std::recursive_mutex m;
+ m.try_lock();
+ m.unlock();
+ }
+ {
+ std::timed_mutex m;
+ m.try_lock();
+ m.unlock();
+ m.try_lock_for(std::chrono::seconds(1));
+ m.unlock();
+ m.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));
+ m.unlock();
+ }
+ {
+ std::recursive_timed_mutex m;
+ m.try_lock();
+ m.unlock();
+ m.try_lock_for(std::chrono::seconds(1));
+ m.unlock();
+ m.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));
+ m.unlock();
+ }
+ {
+ std::mutex m;
+ std::unique_lock<std::mutex> lk(m);
+ lk.unlock();
+ lk.try_lock();
+ }
+ {
+ std::timed_mutex m;
+ std::unique_lock<std::timed_mutex> lk(m);
+ lk.unlock();
+ lk.try_lock();
+ lk.unlock();
+ lk.try_lock_for(std::chrono::seconds(1));
+ lk.unlock();
+ lk.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));
+ lk.unlock();
+ }
+#if TEST_STD_VER > 11
+ {
+ std::shared_timed_mutex m;
+ m.try_lock();
+ m.unlock();
+ m.try_lock_for(std::chrono::seconds(1));
+ m.unlock();
+ m.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));
+ m.unlock();
+ m.try_lock_shared();
+ m.unlock();
+ m.try_lock_shared_for(std::chrono::seconds(1));
+ m.unlock();
+ m.try_lock_shared_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));
+ m.unlock();
+ }
+ {
+ std::shared_timed_mutex m;
+ std::shared_lock<std::shared_timed_mutex> lk(m);
+ lk.unlock();
+ lk.try_lock();
+ lk.unlock();
+ lk.try_lock_for(std::chrono::seconds(1));
+ lk.unlock();
+ lk.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));
+ lk.unlock();
+ }
+#endif
+#if TEST_STD_VER > 14
+ {
+ std::shared_mutex m;
+ m.try_lock();
+ m.unlock();
+ m.try_lock_shared();
+ m.unlock();
+ };
+#endif
+}
Index: test/libcxx/thread/thread.mutex/try_lock_no_discard.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/thread/thread.mutex/try_lock_no_discard.fail.cpp
@@ -0,0 +1,103 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: libcpp-has-no-threads
+// REQUIRES: verify-diagnostics
+
+// test the generated [[no_discard]] warnings
+
+#include <mutex>
+#include <shared_mutex>
+
+#include "test_macros.h"
+
+int main() {
+ {
+ std::mutex m;
+ m.try_lock(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ }
+ {
+ std::recursive_mutex m;
+ m.try_lock(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ }
+ {
+ std::timed_mutex m;
+ m.try_lock(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_for(std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ }
+ {
+ std::recursive_timed_mutex m;
+ m.try_lock(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_for(std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ }
+ {
+ std::mutex m;
+ std::unique_lock<std::mutex> lk(m);
+ lk.unlock();
+ lk.try_lock(); // expected-warning {{ignoring return value}}
+ }
+ {
+ std::timed_mutex m;
+ std::unique_lock<std::timed_mutex> lk(m);
+ lk.unlock();
+ lk.try_lock(); // expected-warning {{ignoring return value}}
+ lk.unlock();
+ lk.try_lock_for(std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ lk.unlock();
+ lk.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ lk.unlock();
+ }
+#if TEST_STD_VER > 11
+ {
+ std::shared_timed_mutex m;
+ m.try_lock(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_for(std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_shared(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_shared_for(std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_shared_until(std::chrono::steady_clock::now() + std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ m.unlock();
+ }
+ {
+ std::shared_timed_mutex m;
+ std::shared_lock<std::shared_timed_mutex> lk(m);
+ lk.unlock();
+ lk.try_lock(); // expected-warning {{ignoring return value}}
+ lk.unlock();
+ lk.try_lock_for(std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ lk.unlock();
+ lk.try_lock_until(std::chrono::steady_clock::now() + std::chrono::seconds(1)); // expected-warning {{ignoring return value}}
+ lk.unlock();
+ }
+#endif
+#if TEST_STD_VER > 14
+ {
+ std::shared_mutex m;
+ m.try_lock(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ m.try_lock_shared(); // expected-warning {{ignoring return value}}
+ m.unlock();
+ };
+#endif
+}
Index: test/libcxx/test/config.py
===================================================================
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -249,6 +249,8 @@
['-Xclang', '-verify-ignore-unexpected'])
self.lit_config.note(
"inferred use_clang_verify as: %r" % self.use_clang_verify)
+ if self.use_clang_verify:
+ self.config.available_features.add('verify-diagnostics')
def configure_use_thread_safety(self):
'''If set, run clang with -verify on failing tests.'''
Index: test/libcxx/containers/no-discard.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/containers/no-discard.fail.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-diagnostics
+
+// test the generated [[no_discard]] warnings
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <forward_list>
+#include <set>
+#include <map>
+#include <unordered_set>
+#include <unordered_map>
+#include <string>
+#include <string_view>
+
+// Note: -Wunused-result is not emitted from within function templates so
+// we instead use a macro to avoid duplication.
+#define TEST_WARNING4(...) \
+ do { __VA_ARGS__ C; C.empty(); C.size(); C.capacity(); C.max_size(); } while (false)
+
+#define TEST_WARNING3(...) \
+ do { __VA_ARGS__ C; C.empty(); C.size(); C.max_size(); } while (false)
+
+int main() {
+ // std::vector
+ {
+ TEST_WARNING4(std::vector<int>); // expected-warning 4 {{ignoring return value}}
+ TEST_WARNING4(std::vector<bool>); // expected-warning 4 {{ignoring return value}}
+ }
+ // std::string
+ {
+ TEST_WARNING4(std::string); // expected-warning 4 {{ignoring return value}}
+ std::string s;
+ s.length(); // expected-warning {{ignoring return value}}
+ }
+ {
+ TEST_WARNING3(std::string_view); // expected-warning 3 {{ignoring return value}}
+ std::string_view s;
+ s.length(); // expected-warning {{ignoring return value}}
+ }
+ {
+ TEST_WARNING3(std::list<int>); // expected-warning 3 {{ignoring return value}}
+ }
+ {
+ std::forward_list<int> C;
+ C.empty(); // expected-warning {{ignoring return value}}
+ C.max_size(); // expected-warning {{ignoring return value}}
+ }
+ {
+ TEST_WARNING3(std::set<int>); // expected-warning 3 {{ignoring return value}}
+ TEST_WARNING3(std::multiset<int>); // expected-warning 3 {{ignoring return value}}
+ }
+ {
+ TEST_WARNING3(std::map<int, int>); // expected-warning 3 {{ignoring return value}}
+ TEST_WARNING3(std::multimap<int, int>); // expected-warning 3 {{ignoring return value}}
+ }
+ {
+ TEST_WARNING3(std::unordered_set<int>); // expected-warning 3 {{ignoring return value}}
+ TEST_WARNING3(std::unordered_multiset<int>); // expected-warning 3 {{ignoring return value}}
+ }
+ {
+ TEST_WARNING3(std::unordered_map<int, int>); // expected-warning 3 {{ignoring return value}}
+ TEST_WARNING3(std::unordered_multimap<int, int>); // expected-warning 3 {{ignoring return value}}
+ }
+}
Index: test/libcxx/containers/no-discard-disable.fail.cpp
===================================================================
--- /dev/null
+++ test/libcxx/containers/no-discard-disable.fail.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: verify-diagnostics
+
+// test the generated [[no_discard]] warnings
+
+#define _LIBCPP_DISABLE_NO_DISCARD_CONTAINER_OBSERVERS
+#include <vector>
+#include <deque>
+#include <list>
+#include <forward_list>
+#include <set>
+#include <map>
+#include <unordered_set>
+#include <unordered_map>
+#include <string>
+#include <string_view>
+
+// Note: -Wunused-result is not emitted from within function templates so
+// we instead use a macro to avoid duplication.
+#define TEST_WARNING4(...) \
+ do { __VA_ARGS__ C; C.empty(); C.size(); C.capacity(); C.max_size(); } while (false)
+
+#define TEST_WARNING3(...) \
+ do { __VA_ARGS__ C; C.empty(); C.size(); C.max_size(); } while (false)
+
+int main() {
+ // expected-no-diagnostics
+ // std::vector
+ {
+ TEST_WARNING4(std::vector<int>);
+ TEST_WARNING4(std::vector<bool>);
+ }
+ // std::string
+ {
+ TEST_WARNING4(std::string);
+ std::string s;
+ s.length();
+ }
+ {
+ TEST_WARNING3(std::string_view);
+ std::string_view s;
+ s.length();
+ }
+ {
+ TEST_WARNING3(std::list<int>);
+ }
+ {
+ std::forward_list<int> C;
+ C.empty();
+ C.max_size();
+ }
+ {
+ TEST_WARNING3(std::set<int>);
+ TEST_WARNING3(std::multiset<int>);
+ }
+ {
+ TEST_WARNING3(std::map<int, int>);
+ TEST_WARNING3(std::multimap<int, int>);
+ }
+ {
+ TEST_WARNING3(std::unordered_set<int>);
+ TEST_WARNING3(std::unordered_multiset<int>);
+ }
+ {
+ TEST_WARNING3(std::unordered_map<int, int>);
+ TEST_WARNING3(std::unordered_multimap<int, int>);
+ }
+}
Index: include/vector
===================================================================
--- include/vector
+++ include/vector
@@ -627,16 +627,16 @@
const_reverse_iterator crend() const _NOEXCEPT
{return rend();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT
{return static_cast<size_type>(this->__end_ - this->__begin_);}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type capacity() const _NOEXCEPT
{return __base::capacity();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT
{return this->__begin_ == this->__end_;}
- size_type max_size() const _NOEXCEPT;
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS size_type max_size() const _NOEXCEPT;
void reserve(size_type __n);
void shrink_to_fit() _NOEXCEPT;
@@ -2242,14 +2242,14 @@
_LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT
{return allocator_type(this->__alloc());}
- size_type max_size() const _NOEXCEPT;
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS size_type max_size() const _NOEXCEPT;
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type capacity() const _NOEXCEPT
{return __internal_cap_to_external(__cap());}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT
{return __size_;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT
{return __size_ == 0;}
void reserve(size_type __n);
Index: include/unordered_set
===================================================================
--- include/unordered_set
+++ include/unordered_set
@@ -454,11 +454,11 @@
allocator_type get_allocator() const _NOEXCEPT
{return allocator_type(__table_.__node_alloc());}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __table_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __table_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __table_.max_size();}
_LIBCPP_INLINE_VISIBILITY
@@ -992,11 +992,11 @@
allocator_type get_allocator() const _NOEXCEPT
{return allocator_type(__table_.__node_alloc());}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __table_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __table_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __table_.max_size();}
_LIBCPP_INLINE_VISIBILITY
Index: include/unordered_map
===================================================================
--- include/unordered_map
+++ include/unordered_map
@@ -893,11 +893,11 @@
allocator_type get_allocator() const _NOEXCEPT
{return allocator_type(__table_.__node_alloc());}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __table_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __table_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __table_.max_size();}
_LIBCPP_INLINE_VISIBILITY
@@ -1647,11 +1647,11 @@
allocator_type get_allocator() const _NOEXCEPT
{return allocator_type(__table_.__node_alloc());}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __table_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __table_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __table_.max_size();}
_LIBCPP_INLINE_VISIBILITY
Index: include/thread
===================================================================
--- include/thread
+++ include/thread
@@ -362,7 +362,7 @@
__decay_copy(_VSTD::forward<_Args>(__args))...));
int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
if (__ec == 0)
- __p.release();
+ (void)__p.release();
else
__throw_system_error(__ec, "thread constructor failed");
}
@@ -397,7 +397,7 @@
_PairPtr __pp(new _InvokePair(__f));
int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
if (__ec == 0)
- __pp.release();
+ (void)__pp.release();
else
__throw_system_error(__ec, "thread constructor failed");
}
Index: include/string_view
===================================================================
--- include/string_view
+++ include/string_view
@@ -241,17 +241,17 @@
const_reverse_iterator crend() const _NOEXCEPT { return const_reverse_iterator(cbegin()); }
// [string.view.capacity], capacity
- _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_CONSTEXPR _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT { return __size; }
- _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_CONSTEXPR _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type length() const _NOEXCEPT { return __size; }
- _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_CONSTEXPR _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT { return numeric_limits<size_type>::max(); }
- _LIBCPP_CONSTEXPR bool _LIBCPP_INLINE_VISIBILITY
- empty() const _NOEXCEPT { return __size == 0; }
+ _LIBCPP_CONSTEXPR _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ bool empty() const _NOEXCEPT { return __size == 0; }
// [string.view.access], element access
_LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
Index: include/string
===================================================================
--- include/string
+++ include/string
@@ -879,11 +879,15 @@
const_reverse_iterator crend() const _NOEXCEPT
{return rend();}
- _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ size_type size() const _NOEXCEPT
{return __is_long() ? __get_long_size() : __get_short_size();}
- _LIBCPP_INLINE_VISIBILITY size_type length() const _NOEXCEPT {return size();}
- _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT;
- _LIBCPP_INLINE_VISIBILITY size_type capacity() const _NOEXCEPT
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ size_type length() const _NOEXCEPT {return size();}
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ size_type max_size() const _NOEXCEPT;
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ size_type capacity() const _NOEXCEPT
{return (__is_long() ? __get_long_cap()
: static_cast<size_type>(__min_cap)) - 1;}
@@ -895,7 +899,8 @@
void shrink_to_fit() _NOEXCEPT {reserve();}
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT;
- _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return size() == 0;}
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ bool empty() const _NOEXCEPT {return size() == 0;}
_LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __pos) const _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY reference operator[](size_type __pos) _NOEXCEPT;
Index: include/shared_mutex
===================================================================
--- include/shared_mutex
+++ include/shared_mutex
@@ -159,12 +159,12 @@
// Exclusive ownership
void lock(); // blocking
- bool try_lock();
+ _LIBCPP_NO_DISCARD bool try_lock();
void unlock();
// Shared ownership
void lock_shared(); // blocking
- bool try_lock_shared();
+ _LIBCPP_NO_DISCARD bool try_lock_shared();
void unlock_shared();
// typedef implementation-defined native_handle_type; // See 30.2.3
@@ -185,12 +185,14 @@
// Exclusive ownership
_LIBCPP_INLINE_VISIBILITY void lock() { return __base.lock(); }
- _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
+ _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_INLINE_VISIBILITY
+ bool try_lock() { return __base.try_lock(); }
_LIBCPP_INLINE_VISIBILITY void unlock() { return __base.unlock(); }
// Shared ownership
_LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); }
- _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
+ _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_INLINE_VISIBILITY
+ bool try_lock_shared() { return __base.try_lock_shared(); }
_LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); }
// typedef __shared_mutex_base::native_handle_type native_handle_type;
@@ -211,31 +213,31 @@
// Exclusive ownership
void lock();
- bool try_lock();
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock();
template <class _Rep, class _Period>
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_INLINE_VISIBILITY
bool
try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
{
return try_lock_until(chrono::steady_clock::now() + __rel_time);
}
template <class _Clock, class _Duration>
- bool
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool
try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
void unlock();
// Shared ownership
void lock_shared();
- bool try_lock_shared();
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock_shared();
template <class _Rep, class _Period>
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_INLINE_VISIBILITY
bool
try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
}
template <class _Clock, class _Duration>
- bool
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool
try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
void unlock_shared();
};
@@ -391,10 +393,12 @@
}
void lock();
- bool try_lock();
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock();
template <class Rep, class Period>
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
Index: include/set
===================================================================
--- include/set
+++ include/set
@@ -579,11 +579,11 @@
_LIBCPP_INLINE_VISIBILITY
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __tree_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __tree_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __tree_.max_size();}
// modifiers:
@@ -991,11 +991,11 @@
_LIBCPP_INLINE_VISIBILITY
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __tree_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __tree_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __tree_.max_size();}
// modifiers:
Index: include/regex
===================================================================
--- include/regex
+++ include/regex
@@ -3015,7 +3015,7 @@
{
unique_ptr<__node> __h(new __end_state<_CharT>);
__start_.reset(new __empty_state<_CharT>(__h.get()));
- __h.release();
+ (void)__h.release();
__end_ = __start_.get();
}
switch (__flags_ & 0x1F0)
@@ -4608,7 +4608,7 @@
__s->first(), __e1.get(), __mexp_begin, __mexp_end, __greedy,
__min, __max));
__s->first() = nullptr;
- __e1.release();
+ (void)__e1.release();
__end_->first() = new __repeat_one_loop<_CharT>(__e2.get());
__end_ = __e2->second();
__s->first() = __e2.release();
Index: include/mutex
===================================================================
--- include/mutex
+++ include/mutex
@@ -218,7 +218,7 @@
public:
void lock();
- bool try_lock() _NOEXCEPT;
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock() _NOEXCEPT;
void unlock() _NOEXCEPT;
typedef __libcpp_mutex_t* native_handle_type;
@@ -241,12 +241,13 @@
public:
void lock();
- bool try_lock() _NOEXCEPT;
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock() _NOEXCEPT;
template <class _Rep, class _Period>
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_INLINE_VISIBILITY
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
{return try_lock_until(chrono::steady_clock::now() + __d);}
template <class _Clock, class _Duration>
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
void unlock() _NOEXCEPT;
};
@@ -284,12 +285,13 @@
public:
void lock();
- bool try_lock() _NOEXCEPT;
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock() _NOEXCEPT;
template <class _Rep, class _Period>
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_INLINE_VISIBILITY
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
{return try_lock_until(chrono::steady_clock::now() + __d);}
template <class _Clock, class _Duration>
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
void unlock() _NOEXCEPT;
};
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -649,6 +649,12 @@
#pragma GCC system_header
#endif
+#ifndef _LIBCPP_DISABLE_NO_DISCARD_SMART_PTR_OBSERVERS
+# define _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_NO_DISCARD
+#else
+# define _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS
+#endif
+
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ValueType>
@@ -2756,18 +2762,24 @@
return *this;
}
- _LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference<_Tp>::type operator*() const
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ typename add_lvalue_reference<_Tp>::type operator*() const
{return *__ptr_.first();}
- _LIBCPP_INLINE_VISIBILITY pointer operator->() const _NOEXCEPT {return __ptr_.first();}
- _LIBCPP_INLINE_VISIBILITY pointer get() const _NOEXCEPT {return __ptr_.first();}
- _LIBCPP_INLINE_VISIBILITY _Dp_reference get_deleter() _NOEXCEPT
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ pointer operator->() const _NOEXCEPT {return __ptr_.first();}
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ pointer get() const _NOEXCEPT {return __ptr_.first();}
+ _LIBCPP_INLINE_VISIBILITY _Dp_reference get_deleter() _NOEXCEPT
{return __ptr_.second();}
_LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT
{return __ptr_.second();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
{return __ptr_.first() != nullptr;}
+#ifndef _LIBCPP_DISABLE_NO_DISCARD_UNIQUE_PTR_RELEASE
+ _LIBCPP_NO_DISCARD
+#endif
_LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT
{
pointer __t = __ptr_.first();
@@ -2948,17 +2960,22 @@
return *this;
}
- _LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference<_Tp>::type operator[](size_t __i) const
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ typename add_lvalue_reference<_Tp>::type operator[](size_t __i) const
{return __ptr_.first()[__i];}
- _LIBCPP_INLINE_VISIBILITY pointer get() const _NOEXCEPT {return __ptr_.first();}
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
+ pointer get() const _NOEXCEPT {return __ptr_.first();}
_LIBCPP_INLINE_VISIBILITY _Dp_reference get_deleter() _NOEXCEPT
{return __ptr_.second();}
_LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT
{return __ptr_.second();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
{return __ptr_.first() != nullptr;}
+#ifndef _LIBCPP_DISABLE_NO_DISCARD_UNIQUE_PTR_RELEASE
+ _LIBCPP_NO_DISCARD
+#endif
_LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT
{
pointer __t = __ptr_.first();
@@ -4022,7 +4039,7 @@
virtual void __on_zero_shared() _NOEXCEPT;
virtual void __on_zero_shared_weak() _NOEXCEPT;
public:
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD _LIBCPP_INLINE_VISIBILITY
_Tp* get() _NOEXCEPT {return &__data_.second();}
};
@@ -4229,18 +4246,18 @@
_LIBCPP_INLINE_VISIBILITY
reset(_Yp* __p, _Dp __d, _Alloc __a);
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
element_type* get() const _NOEXCEPT {return __ptr_;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT
{return *__ptr_;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
element_type* operator->() const _NOEXCEPT {return __ptr_;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool unique() const _NOEXCEPT {return use_count() == 1;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return get() != 0;}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
@@ -4355,7 +4372,7 @@
unique_ptr<_Yp> __hold(__p);
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk;
__cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), allocator<_Yp>());
- __hold.release();
+ (void)__hold.release();
__enable_weak_this(__p, __p);
}
@@ -4562,7 +4579,7 @@
__cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), allocator<_Yp>());
__enable_weak_this(__r.get(), __r.get());
}
- __r.release();
+ (void)__r.release();
}
template<class _Tp>
@@ -5327,10 +5344,10 @@
_LIBCPP_INLINE_VISIBILITY
void reset() _NOEXCEPT;
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
long use_count() const _NOEXCEPT
{return __cntrl_ ? __cntrl_->use_count() : 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_SMART_PTR_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool expired() const _NOEXCEPT
{return __cntrl_ == 0 || __cntrl_->use_count() == 0;}
shared_ptr<_Tp> lock() const _NOEXCEPT;
Index: include/map
===================================================================
--- include/map
+++ include/map
@@ -1018,11 +1018,11 @@
_LIBCPP_INLINE_VISIBILITY
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __tree_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __tree_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __tree_.max_size();}
mapped_type& operator[](const key_type& __k);
@@ -1744,11 +1744,11 @@
_LIBCPP_INLINE_VISIBILITY
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return __tree_.size() == 0;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return __tree_.size();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT {return __tree_.max_size();}
_LIBCPP_INLINE_VISIBILITY
Index: include/locale
===================================================================
--- include/locale
+++ include/locale
@@ -2767,7 +2767,7 @@
if (__t == 0)
__throw_bad_alloc();
if (__owns)
- __b.release();
+ (void)__b.release();
__b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
__new_cap /= sizeof(_Tp);
__n = __b.get() + __n_off;
Index: include/list
===================================================================
--- include/list
+++ include/list
@@ -898,11 +898,11 @@
_LIBCPP_INLINE_VISIBILITY
allocator_type get_allocator() const _NOEXCEPT;
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type size() const _NOEXCEPT {return base::__sz();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT {return base::empty();}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT
{return numeric_limits<difference_type>::max();}
@@ -1426,7 +1426,7 @@
#else
__r = iterator(__hold->__as_link());
#endif
- __hold.release();
+ (void)__hold.release();
iterator __e = __r;
#ifndef _LIBCPP_NO_EXCEPTIONS
try
@@ -1438,7 +1438,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
__e.__ptr_->__next_ = __hold->__as_link();
__hold->__prev_ = __e.__ptr_;
- __hold.release();
+ (void)__hold.release();
}
#ifndef _LIBCPP_NO_EXCEPTIONS
}
@@ -1494,7 +1494,7 @@
#else
__r = iterator(__hold.get()->__as_link());
#endif
- __hold.release();
+ (void)__hold.release();
iterator __e = __r;
#ifndef _LIBCPP_NO_EXCEPTIONS
try
@@ -1506,7 +1506,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), *__f);
__e.__ptr_->__next_ = __hold.get()->__as_link();
__hold->__prev_ = __e.__ptr_;
- __hold.release();
+ (void)__hold.release();
}
#ifndef _LIBCPP_NO_EXCEPTIONS
}
@@ -1545,7 +1545,7 @@
__link_pointer __nl = __hold->__as_link();
__link_nodes_at_front(__nl, __nl);
++base::__sz();
- __hold.release();
+ (void)__hold.release();
}
template <class _Tp, class _Alloc>
@@ -1558,7 +1558,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
__link_nodes_at_back(__hold.get()->__as_link(), __hold.get()->__as_link());
++base::__sz();
- __hold.release();
+ (void)__hold.release();
}
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
@@ -1573,7 +1573,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x));
__link_nodes_at_front(__hold.get()->__as_link(), __hold.get()->__as_link());
++base::__sz();
- __hold.release();
+ (void)__hold.release();
}
template <class _Tp, class _Alloc>
@@ -1586,7 +1586,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x));
__link_nodes_at_back(__hold.get()->__as_link(), __hold.get()->__as_link());
++base::__sz();
- __hold.release();
+ (void)__hold.release();
}
#ifndef _LIBCPP_HAS_NO_VARIADICS
@@ -1638,7 +1638,7 @@
__link_pointer __nl = __hold.get()->__as_link();
__link_nodes(__p.__ptr_, __nl, __nl);
++base::__sz();
- __hold.release();
+ (void)__hold.release();
#if _LIBCPP_DEBUG_LEVEL >= 2
return iterator(__nl, this);
#else
@@ -1665,7 +1665,7 @@
__link_pointer __nl = __hold->__as_link();
__link_nodes(__p.__ptr_, __nl, __nl);
++base::__sz();
- __hold.release();
+ (void)__hold.release();
#if _LIBCPP_DEBUG_LEVEL >= 2
return iterator(__nl, this);
#else
@@ -1851,7 +1851,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_));
__e.__ptr_->__next_ = __hold.get()->__as_link();
__hold->__prev_ = __e.__ptr_;
- __hold.release();
+ (void)__hold.release();
}
#ifndef _LIBCPP_NO_EXCEPTIONS
}
@@ -1911,7 +1911,7 @@
__node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
__e.__ptr_->__next_ = __hold.get()->__as_link();
__hold->__prev_ = __e.__ptr_;
- __hold.release();
+ (void)__hold.release();
}
#ifndef _LIBCPP_NO_EXCEPTIONS
}
Index: include/forward_list
===================================================================
--- include/forward_list
+++ include/forward_list
@@ -730,10 +730,10 @@
const_iterator cbefore_begin() const _NOEXCEPT
{return const_iterator(base::__before_begin());}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT
{return base::__before_begin()->__next_ == nullptr;}
- _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT
{return numeric_limits<size_type>::max();}
Index: include/ext/hash_map
===================================================================
--- include/ext/hash_map
+++ include/ext/hash_map
@@ -693,7 +693,7 @@
return __i->second;
__node_holder __h = __construct_node(__k);
pair<iterator, bool> __r = __table_.__node_insert_unique(__h.get());
- __h.release();
+ (void)__h.release();
return __r.first->second;
}
Index: include/deque
===================================================================
--- include/deque
+++ include/deque
@@ -2317,7 +2317,7 @@
__alloc_traits::allocate(__a, __base::__block_size),
_Dp(__a, __base::__block_size));
__buf.push_back(__hold.get());
- __hold.release();
+ (void)__hold.release();
for (typename __base::__map_pointer __i = __base::__map_.begin();
__i != __base::__map_.end(); ++__i)
@@ -2460,7 +2460,7 @@
__alloc_traits::allocate(__a, __base::__block_size),
_Dp(__a, __base::__block_size));
__buf.push_back(__hold.get());
- __hold.release();
+ (void)__hold.release();
for (typename __base::__map_pointer __i = __base::__map_.end();
__i != __base::__map_.begin();)
Index: include/algorithm
===================================================================
--- include/algorithm
+++ include/algorithm
@@ -3931,7 +3931,7 @@
__d.__incr((value_type*)0);
}
}
- __h.release();
+ (void)__h.release();
}
}
@@ -4661,14 +4661,14 @@
{
for (; __first2 != __last2; ++__first2, ++__result, __d.__incr((value_type*)0))
::new (__result) value_type(_VSTD::move(*__first2));
- __h.release();
+ (void)__h.release();
return;
}
if (__first2 == __last2)
{
for (; __first1 != __last1; ++__first1, ++__result, __d.__incr((value_type*)0))
::new (__result) value_type(_VSTD::move(*__first1));
- __h.release();
+ (void)__h.release();
return;
}
if (__comp(*__first2, *__first1))
@@ -4752,7 +4752,7 @@
++__first2;
::new(__first2) value_type(_VSTD::move(*__last1));
}
- __h2.release();
+ (void)__h2.release();
return;
}
if (__len <= 8)
Index: include/__mutex_base
===================================================================
--- include/__mutex_base
+++ include/__mutex_base
@@ -32,6 +32,12 @@
# endif
#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
+#ifndef _LIBCPP_DISABLE_NO_DISCARD_TRY_LOCK
+# define _LIBCPP_NO_DISCARD_TRY_LOCK _LIBCPP_NO_DISCARD
+#else
+# define _LIBCPP_NO_DISCARD_TRY_LOCK
+#endif
+
class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
{
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
@@ -55,6 +61,7 @@
public:
void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
@@ -182,11 +189,13 @@
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
void lock();
- bool try_lock();
+ _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock();
template <class _Rep, class _Period>
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
template <class _Clock, class _Duration>
+ _LIBCPP_NO_DISCARD_TRY_LOCK
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
void unlock();
Index: include/__hash_table
===================================================================
--- include/__hash_table
+++ include/__hash_table
@@ -1608,7 +1608,7 @@
{
__node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__value_));
__node_insert_multi(__h.get());
- __h.release();
+ (void)__h.release();
}
}
}
@@ -2022,7 +2022,7 @@
__node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
pair<iterator, bool> __r = __node_insert_unique(__h.get());
if (__r.second)
- __h.release();
+ (void)__h.release();
return __r;
}
@@ -2033,7 +2033,7 @@
{
__node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
iterator __r = __node_insert_multi(__h.get());
- __h.release();
+ (void)__h.release();
return __r;
}
@@ -2050,7 +2050,7 @@
#endif
__node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
iterator __r = __node_insert_multi(__p, __h.get());
- __h.release();
+ (void)__h.release();
return __r;
}
@@ -2062,7 +2062,7 @@
{
__node_holder __h = __construct_node(__x);
iterator __r = __node_insert_multi(__h.get());
- __h.release();
+ (void)__h.release();
return __r;
}
@@ -2078,7 +2078,7 @@
#endif
__node_holder __h = __construct_node(__x);
iterator __r = __node_insert_multi(__p, __h.get());
- __h.release();
+ (void)__h.release();
return __r;
}
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -900,6 +900,21 @@
#define _LIBCPP_SAFE_STATIC
#endif
+#ifndef _LIBCPP_NO_DISCARD
+# if !defined(_LIBCPP_DISABLE_NO_DISCARD) && \
+ (__has_attribute(warn_unused_result) || _GNUC_VER > 408)
+# define _LIBCPP_NO_DISCARD __attribute__((__warn_unused_result__))
+# else
+# define _LIBCPP_NO_DISCARD
+# endif
+#endif // !defined(_LIBCPP_NO_DISCARD)
+
+#ifndef _LIBCPP_DISABLE_NO_DISCARD_CONTAINER_OBSERVERS
+# define _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_NO_DISCARD
+#else
+# define _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS
+#endif
+
#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700
#define _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
#endif
Index: docs/UsingLibcxx.rst
===================================================================
--- docs/UsingLibcxx.rst
+++ docs/UsingLibcxx.rst
@@ -149,3 +149,28 @@
This macro is used to enable -Wthread-safety annotations on libc++'s
``std::mutex`` and ``std::lock_guard``. By default these annotations are
disabled and must be manually enabled by the user.
+
+**_LIBCPP_NO_DISCARD**
+ This macro is used to annotate various libc++ functions as having a
+ non-discardable return value. This macro is enabled by default.
+
+ **Overriding**: To fully disable libc++'s no-discard attribute users can
+ define `_LIBCPP_DISABLE_NO_DISCARD` before including any headers. It's also
+ possible to disable groups of no-discard checks by defining one of the
+ macros below:
+
+ * **_LIBCPP_DISABLE_NO_DISCARD_UNIQUE_PTR_RELEASE**: Disables no-discard on
+ ``std::unique_ptr<T>::release()``.
+
+ * **_LIBCPP_DISABLE_NO_DISCARD_SMART_PTR_OBSERVERS**: Disables no-discard
+ on non-modifying smart pointer operations such as ``get()`` or
+ ``operator*()``.
+
+ * **_LIBCPP_DISABLE_NO_DISCARD_CONTAINER_OBSERVERS**: Disables
+ no-discard on non-modifying container operations such as the ``size()``,
+ ``empty()``, and ``capacity()`` methods of ``std::vector`` or
+ ``std::string``.
+
+ * **_LIBCPP_DISABLE_NO_DISCARD_TRY_LOCK**: Disables no-discard on the
+ ``try_lock()``, ``try_lock_for()``, and ``try_lock_until()``
+ members of lockable types.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits