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 Smithvoid 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