aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/warn-thread-safety-analysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX/warn-thread-safety-analysis.cpp')
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 4f31d406b5fb..b5d2f8e1de83 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -5091,3 +5091,101 @@ class Foo {
} // end namespace ScopedAdoptTest
+
+namespace TestReferenceNoThreadSafetyAnalysis {
+
+#define TS_UNCHECKED_READ(x) ts_unchecked_read(x)
+
+// Takes a reference to a guarded data member, and returns an unguarded
+// reference.
+template <class T>
+inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
+ return v;
+}
+
+template <class T>
+inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
+ return v;
+}
+
+
+class Foo {
+public:
+ Foo(): a(0) { }
+
+ int a;
+};
+
+
+class Bar {
+public:
+ Bar() : a(0) { }
+
+ Mutex mu;
+ int a GUARDED_BY(mu);
+ Foo foo GUARDED_BY(mu);
+};
+
+
+void test() {
+ Bar bar;
+ const Bar cbar;
+
+ int a = TS_UNCHECKED_READ(bar.a); // nowarn
+ TS_UNCHECKED_READ(bar.a) = 1; // nowarn
+
+ int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn
+ TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn
+
+ int c = TS_UNCHECKED_READ(cbar.a); // nowarn
+}
+
+#undef TS_UNCHECKED_READ
+
+} // end namespace TestReferenceNoThreadSafetyAnalysis
+
+
+namespace GlobalAcquiredBeforeAfterTest {
+
+Mutex mu1;
+Mutex mu2 ACQUIRED_AFTER(mu1);
+
+void test3() {
+ mu2.Lock();
+ mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
+ mu1.Unlock();
+ mu2.Unlock();
+}
+
+} // end namespace GlobalAcquiredBeforeAfterTest
+
+
+namespace LockableUnions {
+
+union LOCKABLE MutexUnion {
+ int a;
+ char* b;
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+};
+
+MutexUnion muun2;
+MutexUnion muun1 ACQUIRED_BEFORE(muun2);
+
+void test() {
+ muun2.Lock();
+ muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}
+ muun1.Unlock();
+ muun2.Unlock();
+}
+
+} // end namespace LockableUnions
+
+// This used to crash.
+class acquired_before_empty_str {
+ void WaitUntilSpaceAvailable() {
+ lock_.ReaderLock(); // expected-note {{acquired here}}
+ } // expected-warning {{mutex 'lock_' is still held at the end of function}}
+ Mutex lock_ ACQUIRED_BEFORE("");
+};