EricWF updated this revision to Diff 77772.
EricWF added a comment.

Add final touches. This patch is ready to go.

@chandlerc mentioned he would still like to see more per-function granularity 
for enabling/disabling the libc++ [[nodiscard]] macro in order to ease adoption 
in large code bases. However I'm concerned about the cost of maintaining 100+ 
user-visible configuration macros. This current patch attempts to find a happy 
medium by grouping similar functions  into a single macro; which can be 
sub-divided further if needed.

As a general rule functions where [[nodiscard]] may yield false positives (ie 
`unique_ptr::release()`) should always have their own group, since fixing the 
false-positives is a stylistic change. Functions where a discarded value is 
always a bug, either for correctness reasons (ie `try_lock()`) or  because the 
call has no side-effects (ie `string::empty`), may be grouped together as 
appropriate; Warnings generated by these groups should either be rare or high 
priority bugs. Dividing groups in this manner attempts to maximize adaptability 
while being reasonably maintainable.

@mclow.lists Any last words?


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,77 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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::deque<int>); // expected-warning 3 {{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,79 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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::deque<int>);
+  }
+  {
+    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_INTERNAL bool try_lock();
     void unlock();
 
     // Shared ownership
     void lock_shared(); // blocking
-    bool try_lock_shared();
+    _LIBCPP_NO_DISCARD_INTERNAL 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_INTERNAL _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
@@ -1306,15 +1306,15 @@
         {return const_reverse_iterator(__base::begin());}
 
     // capacity:
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
     size_type size() const _NOEXCEPT {return __base::size();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
     size_type max_size() const _NOEXCEPT
         {return __alloc_traits::max_size(__base::__alloc());}
     void resize(size_type __n);
     void resize(size_type __n, const value_type& __v);
     void shrink_to_fit() _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_NO_DISCARD_CONTAINER_OBSERVERS _LIBCPP_INLINE_VISIBILITY
     bool empty() const _NOEXCEPT {return __base::size() == 0;}
 
     // element access:
@@ -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,24 @@
 #define _LIBCPP_SAFE_STATIC
 #endif
 
+#if __has_attribute(__warn_unused_result__) || _GNUC_VER > 408
+# define _LIBCPP_NO_DISCARD_INTERNAL __attribute__((__warn_unused_result__))
+#else
+# define _LIBCPP_NO_DISCARD_INTERNAL
+#endif
+
+#ifndef _LIBCPP_DISABLE_NO_DISCARD
+# define _LIBCPP_NO_DISCARD _LIBCPP_NO_DISCARD_INTERNAL
+#else
+# define _LIBCPP_NO_DISCARD
+#endif
+
+#if !defined(_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_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_SMART_PTR_OBSERVERS**: Disables no-discard
+      on non-modifying smart pointer operations such as ``get()`` or
+      ``operator*()``.
+
+    * **_LIBCPP_DISABLE_NO_DISCARD_TRY_LOCK**: Disables no-discard on the
+      ``try_lock()``, ``try_lock_for()``, and ``try_lock_until()``
+      members of lockable types.
+
+    * **_LIBCPP_DISABLE_NO_DISCARD_UNIQUE_PTR_RELEASE**: Disables no-discard on
+      ``std::unique_ptr<T>::release()``.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to