133bddbd6SRichard Smith // RUN: %clang_cc1 -std=c++11 %s -verify -Wthread-safety-analysis
233bddbd6SRichard Smith 
333bddbd6SRichard Smith class Mutex {
433bddbd6SRichard Smith public:
533bddbd6SRichard Smith   void Lock() __attribute__((exclusive_lock_function()));
633bddbd6SRichard Smith   void Unlock() __attribute__((unlock_function()));
733bddbd6SRichard Smith };
833bddbd6SRichard Smith 
933bddbd6SRichard Smith class A {
1033bddbd6SRichard Smith public:
1133bddbd6SRichard Smith   Mutex mu1, mu2;
1233bddbd6SRichard Smith 
foo()1333bddbd6SRichard Smith   void foo() __attribute__((exclusive_locks_required(mu1))) __attribute__((exclusive_locks_required(mu2))) {}
1433bddbd6SRichard Smith 
bar()1533bddbd6SRichard Smith   template <class T> void bar() __attribute__((exclusive_locks_required(mu1))) __attribute__((exclusive_locks_required(mu2))) {
1633bddbd6SRichard Smith     foo();
1733bddbd6SRichard Smith   }
1833bddbd6SRichard Smith };
1933bddbd6SRichard Smith 
f()2033bddbd6SRichard Smith void f() {
2133bddbd6SRichard Smith   A a;
2233bddbd6SRichard Smith   a.mu1.Lock();
2333bddbd6SRichard Smith   a.mu2.Lock();
2433bddbd6SRichard Smith   a.bar<int>();
2533bddbd6SRichard Smith   a.mu2.Unlock();
26*b4025806SRichard Trieu   a.bar<int>(); // expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu2' exclusively}}
2733bddbd6SRichard Smith   a.mu1.Unlock();
28*b4025806SRichard Trieu   a.bar<int>(); // expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu1' exclusively}} \
29*b4025806SRichard Trieu                    expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu2' exclusively}}
3033bddbd6SRichard Smith }
31