// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This is a "No Compile Test" suite. // https://dev.chromium.org/developers/testing/no-compile-tests #include "base/thread_annotations.h" namespace { class LOCKABLE Lock { public: void Acquire() EXCLUSIVE_LOCK_FUNCTION() {} void Release() UNLOCK_FUNCTION() {} }; class SCOPED_LOCKABLE AutoLock { public: AutoLock(Lock& lock) EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) { lock.Acquire(); } ~AutoLock() UNLOCK_FUNCTION() { lock_.Release(); } private: Lock& lock_; }; class ThreadSafe { public: void BuggyIncrement(); private: Lock lock_; int counter_ GUARDED_BY(lock_); }; #if defined(NCTEST_LOCK_WITHOUT_UNLOCK) // [r"fatal error: mutex 'lock_' is still held at the end of function"] void ThreadSafe::BuggyIncrement() { lock_.Acquire(); ++counter_; // Forgot to release the lock. } #elif defined(NCTEST_ACCESS_WITHOUT_LOCK) // [r"fatal error: writing variable 'counter_' requires holding mutex 'lock_' exclusively"] void ThreadSafe::BuggyIncrement() { // Member access without holding the lock guarding it. ++counter_; } #elif defined(NCTEST_ACCESS_WITHOUT_SCOPED_LOCK) // [r"fatal error: writing variable 'counter_' requires holding mutex 'lock_' exclusively"] void ThreadSafe::BuggyIncrement() { { AutoLock auto_lock(lock_); // The AutoLock will go out of scope before the guarded member access. } ++counter_; } #elif defined(NCTEST_GUARDED_BY_WRONG_TYPE) // [r"fatal error: 'guarded_by' attribute requires arguments whose type is annotated"] int not_lockable; int global_counter GUARDED_BY(not_lockable); // Defined to avoid link error. void ThreadSafe::BuggyIncrement() { } #endif } // anonymous namespace