diff options
| author | DeLesley Hutchins <delesley@google.com> | 2014-07-28 15:57:27 +0000 |
|---|---|---|
| committer | DeLesley Hutchins <delesley@google.com> | 2014-07-28 15:57:27 +0000 |
| commit | ea1f83385fab96b5274fb60402e7ce6d0925a2f8 (patch) | |
| tree | d4d7a5c259719a2a3233373767d3ac8058e1a6c4 /clang/test | |
| parent | 51510e7f4c38972b4eef7f5b943aac6d9044cb68 (diff) | |
| download | bcm5719-llvm-ea1f83385fab96b5274fb60402e7ce6d0925a2f8.tar.gz bcm5719-llvm-ea1f83385fab96b5274fb60402e7ce6d0925a2f8.zip | |
Thread Safety Analysis: Replace the old and broken SExpr with the new
til::SExpr. This is a large patch, with many small changes to pretty printing
and expression lowering to make the new SExpr representation equivalent in
functionality to the old.
llvm-svn: 214089
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/SemaCXX/warn-thread-safety-analysis.cpp | 151 |
1 files changed, 145 insertions, 6 deletions
diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index 34a33aab42d..17ab4c9afdb 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -95,6 +95,13 @@ public: }; +template <class K, class T> +class MyMap { +public: + T& operator[](const K& k); +}; + + Mutex sls_mu; @@ -2280,6 +2287,15 @@ void test() { (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); (a > 0 ? fooArray[1] : fooArray[b]).a = 0; (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); +} + + +void test2() { + Foo *fooArray; + Bar bar; + int a; + int b; + int c; bar.getFoo().mu_.Lock(); bar.getFooey().a = 0; // \ @@ -2295,20 +2311,20 @@ void test() { bar.getFoo3(a, b).mu_.Lock(); bar.getFoo3(a, c).a = 0; // \ - // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a,c).mu_' exclusively}} \ - // expected-note {{'bar.getFoo3(a,b).mu_'}} + // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \ + // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}} bar.getFoo3(a, b).mu_.Unlock(); getBarFoo(bar, a).mu_.Lock(); getBarFoo(bar, b).a = 0; // \ - // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar,b).mu_' exclusively}} \ - // expected-note {{'getBarFoo(bar,a).mu_'}} + // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \ + // expected-note {{found near match 'getBarFoo(bar, a).mu_'}} getBarFoo(bar, a).mu_.Unlock(); (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \ - // expected-warning {{writing variable 'a' requires holding mutex '((a#_)#_#fooArray[b]).mu_' exclusively}} \ - // expected-note {{'((a#_)#_#fooArray[_]).mu_'}} + // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \ + // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}} (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); } @@ -4378,3 +4394,126 @@ class Foo { }; } // end namespace ThreadAttributesOnLambdas + + + +namespace AttributeExpressionCornerCases { + +class Foo { + int a GUARDED_BY(getMu()); + + Mutex* getMu() LOCK_RETURNED(""); + Mutex* getUniv() LOCK_RETURNED("*"); + + void test1() { + a = 0; + } + + void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) { + a = 0; + } + + void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu); + + void test3() { + foo(nullptr); + } +}; + + +class MapTest { + struct MuCell { Mutex* mu; }; + + MyMap<MyString, Mutex*> map; + MyMap<MyString, MuCell> mapCell; + + int a GUARDED_BY(map["foo"]); + int b GUARDED_BY(mapCell["foo"].mu); + + void test() { + map["foo"]->Lock(); + a = 0; + map["foo"]->Unlock(); + } + + void test2() { + mapCell["foo"].mu->Lock(); + b = 0; + mapCell["foo"].mu->Unlock(); + } +}; + + +class PreciseSmartPtr { + SmartPtr<Mutex> mu; + int val GUARDED_BY(mu); + + static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) { + a.mu->Lock(); + bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \ + // expected-note {{found near match 'a.mu'}} + a.mu->Unlock(); + return result; + } +}; + + +class SmartRedeclare { + SmartPtr<Mutex> mu; + int val GUARDED_BY(mu); + + void test() EXCLUSIVE_LOCKS_REQUIRED(mu); + void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get()); + void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get()); +}; + + +void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) { + val = 0; +} + +void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) { + val = 0; +} + +void SmartRedeclare::test3() { + val = 0; +} + + +namespace CustomMutex { + + +class LOCKABLE BaseMutex { }; +class DerivedMutex : public BaseMutex { }; + +void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m); +void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m); + +static struct DerivedMutex custMu; + +static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { } + +void customTest() { + customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts + doSomethingRequiringLock(); + customUnlock(reinterpret_cast<BaseMutex*>(&custMu)); +} + +} // end namespace CustomMutex + +} // end AttributeExpressionCornerCases + + +namespace ScopedLockReturnedInvalid { + +class Opaque; + +Mutex* getMutex(Opaque* o) LOCK_RETURNED(""); + +void test(Opaque* o) { + MutexLock lock(getMutex(o)); +} + +} // end namespace ScopedLockReturnedInvalid + |

