diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-06-25 18:33:18 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-06-25 18:33:18 +0000 |
commit | 49979f2e38ff97d1e90183f5cfa5d3effcd75c06 (patch) | |
tree | 4942c9bf5af9142ff866b146fd7f03d6d24316fc /clang/test/SemaCXX/warn-thread-safety-analysis.cpp | |
parent | a0e2c04c24e7434fe9cdedbaac6e14030ab61b37 (diff) | |
download | bcm5719-llvm-49979f2e38ff97d1e90183f5cfa5d3effcd75c06.tar.gz bcm5719-llvm-49979f2e38ff97d1e90183f5cfa5d3effcd75c06.zip |
Thread safety analysis: implement lock_returned attribute.
llvm-svn: 159152
Diffstat (limited to 'clang/test/SemaCXX/warn-thread-safety-analysis.cpp')
-rw-r--r-- | clang/test/SemaCXX/warn-thread-safety-analysis.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index 4755daa6e30..8d231bd7f8b 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -2258,3 +2258,106 @@ class Foo { } // end namespace TrylockJoinPoint +namespace LockReturned { + +class Foo { +public: + int a GUARDED_BY(mu_); + void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_); + void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_); + + static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_); + + Mutex* getMu() LOCK_RETURNED(mu_); + + Mutex mu_; + + static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_); +}; + + +// Calls getMu() directly to lock and unlock +void test1(Foo* f1, Foo* f2) { + f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} + + f1->foo2(f2); // expected-warning 2{{calling function 'foo2' requires exclusive lock on 'mu_'}} + Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'mu_'}} + + f1->getMu()->Lock(); + + f1->a = 0; + f1->foo(); + f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}} + + Foo::getMu(f2)->Lock(); + f1->foo2(f2); + Foo::getMu(f2)->Unlock(); + + Foo::sfoo(f1); + + f1->getMu()->Unlock(); +} + + +Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f)); + +class Bar : public Foo { +public: + int b GUARDED_BY(getMu()); + void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu()); + void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu()); + + static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu()); + static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g)); +}; + + + +// Use getMu() within other attributes. +// This requires at lest levels of substitution, more in the case of +void test2(Bar* b1, Bar* b2) { + b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}} + b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'mu_'}} + b1->bar2(b2); // expected-warning 2{{calling function 'bar2' requires exclusive lock on 'mu_'}} + Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'mu_'}} + Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'mu_'}} + + b1->getMu()->Lock(); + + b1->b = 0; + b1->bar(); + b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'mu_'}} + + b2->getMu()->Lock(); + b1->bar2(b2); + + b2->getMu()->Unlock(); + + Bar::sbar(b1); + Bar::sbar2(b1); + + b1->getMu()->Unlock(); +} + + +// Sanity check -- lock the mutex directly, but use attributes that call getMu() +// Also lock the mutex using getFooMu, which calls a lock_returned function. +void test3(Bar* b1, Bar* b2) { + b1->mu_.Lock(); + b1->b = 0; + b1->bar(); + + getFooMu(b2)->Lock(); + b1->bar2(b2); + getFooMu(b2)->Unlock(); + + Bar::sbar(b1); + Bar::sbar2(b1); + + b1->mu_.Unlock(); +} + +} // end namespace LockReturned + + |