Index: include/__mutex_base =================================================================== --- include/__mutex_base +++ include/__mutex_base @@ -62,6 +62,9 @@ void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); +#ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS + const mutex& operator!() const { return *this; } +#endif typedef __libcpp_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_negative.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_negative.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: thread-safety, thread-safety-negative + +// + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(!m))) { + m.lock(); + foo++; + m.unlock(); +} + +int main() { + m.lock(); + increment(); + m.unlock(); +} Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_negative.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_negative.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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: thread-safety, thread-safety-negative + +// + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(!m))) { + m.lock(); + foo++; + m.unlock(); +} + +int main() { + increment(); +} Index: utils/libcxx/test/config.py =================================================================== --- utils/libcxx/test/config.py +++ utils/libcxx/test/config.py @@ -135,6 +135,7 @@ self.configure_cxx_library_root() self.configure_use_clang_verify() self.configure_use_thread_safety() + self.configure_use_thread_safety_negative() self.configure_execute_external() self.configure_ccache() self.configure_compile_flags() @@ -354,6 +355,15 @@ self.config.available_features.add('thread-safety') self.lit_config.note("enabling thread-safety annotations") + def configure_use_thread_safety_negative(self): + '''If set, run clang with -verify on failing tests.''' + has_thread_safety_negative = self.cxx.hasCompileFlag( + '-Werror=thread-safety-negative') + if has_thread_safety_negative: + self.cxx.compile_flags += ['-Werror=thread-safety-negative'] + self.config.available_features.add('thread-safety-negative') + self.lit_config.note("enabling thread-safety-negative annotations") + def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the