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/__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 __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/__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/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/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/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 __r = __table_.__node_insert_unique(__h.get()); - __h.release(); + (void)__h.release(); return __r.first->second; } 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();} @@ -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 @@ -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 @@ -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/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/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(); @@ -4355,7 +4361,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); } 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/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::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/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/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,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 +#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::string_view); + std::string_view 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); + } +} 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 +#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::string_view); // expected-warning 3 {{ignoring return value}} + std::string_view 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}} + } +} 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 +} 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 +} 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; +}