Index: docs/UsingLibcxx.rst =================================================================== --- docs/UsingLibcxx.rst +++ docs/UsingLibcxx.rst @@ -149,3 +149,24 @@ 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::release()``. + + * **_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. 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: 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 + _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); template + _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock(); 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::max();} 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::max();} 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/memory =================================================================== --- include/memory +++ include/memory @@ -2768,6 +2768,9 @@ _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(); @@ -2959,6 +2962,9 @@ _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(); 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 - _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 + _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 - _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 + _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; 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/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 - _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 - 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 - _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 - 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 + _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock_for(const chrono::duration& rel_time); template + _LIBCPP_NO_DISCARD_TRY_LOCK bool try_lock_until(const chrono::time_point& abs_time); void unlock(); 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(__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/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/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/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(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: test/libcxx/containers/no-discard-disable.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/no-discard-disable.fail.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +// 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); + TEST_WARNING4(std::vector); + } + // std::string + { + TEST_WARNING4(std::string); + std::string s; + s.length(); + } + { + TEST_WARNING3(std::list); + } + { + std::forward_list C; + C.empty(); + C.max_size(); + } + { + TEST_WARNING3(std::set); + TEST_WARNING3(std::multiset); + } + { + TEST_WARNING3(std::map); + TEST_WARNING3(std::multimap); + } + { + TEST_WARNING3(std::unordered_set); + TEST_WARNING3(std::unordered_multiset); + } + { + TEST_WARNING3(std::unordered_map); + TEST_WARNING3(std::unordered_multimap); + } +} \ No newline at end of file Index: test/libcxx/containers/no-discard.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/no-discard.fail.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +// 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); // expected-warning 4 {{ignoring return value}} + TEST_WARNING4(std::vector); // 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::list); // expected-warning 3 {{ignoring return value}} + } + { + std::forward_list C; + C.empty(); // expected-warning {{ignoring return value}} + C.max_size(); // expected-warning {{ignoring return value}} + } + { + TEST_WARNING3(std::set); // expected-warning 3 {{ignoring return value}} + TEST_WARNING3(std::multiset); // expected-warning 3 {{ignoring return value}} + } + { + TEST_WARNING3(std::map); // expected-warning 3 {{ignoring return value}} + TEST_WARNING3(std::multimap); // expected-warning 3 {{ignoring return value}} + } + { + TEST_WARNING3(std::unordered_set); // expected-warning 3 {{ignoring return value}} + TEST_WARNING3(std::unordered_multiset); // expected-warning 3 {{ignoring return value}} + } + { + TEST_WARNING3(std::unordered_map); // expected-warning 3 {{ignoring return value}} + TEST_WARNING3(std::unordered_multimap); // expected-warning 3 {{ignoring return value}} + } +} \ No newline at end of file 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/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 +#include + +#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 lk(m); + lk.unlock(); + lk.try_lock(); // expected-warning {{ignoring return value}} + } + { + std::timed_mutex m; + std::unique_lock 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 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 +} \ No newline at end of file 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 +#include + +#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 lk(m); + lk.unlock(); + lk.try_lock(); + } + { + std::timed_mutex m; + std::unique_lock 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 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 +} \ No newline at end of file Index: test/libcxx/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.modifiers/release.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.modifiers/release.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// unique_ptr + +// test release + +#include +#include + +int main() +{ + std::unique_ptr p(new int[3]); + int* i = p.get(); + p.release(); // expected-warning {{ignoring return value of function declared with 'warn_unused_result' attribute}} + delete [] i; +} Index: test/libcxx/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.modifiers/release.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.modifiers/release.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// unique_ptr + +// test release + +#include +#include + +int main() +{ + std::unique_ptr p(new int(3)); + int* i = p.get(); + p.release(); // expected-warning {{ignoring return value of function declared with 'warn_unused_result' attribute}} + delete i; +}