Home | History | Annotate | Download | only in PCH
      1 // Test this without pch.
      2 // RUN: %clang_cc1 -include %s -fsyntax-only -verify -Wthread-safety -std=c++11 %s
      3 
      4 // Test with pch.
      5 // RUN: %clang_cc1 -emit-pch -o %t %s -std=c++11
      6 // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -Wthread-safety -std=c++11 %s
      7 
      8 #ifndef HEADER
      9 #define HEADER
     10 
     11 #define LOCKABLE            __attribute__ ((lockable))
     12 #define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable))
     13 #define GUARDED_BY(x)       __attribute__ ((guarded_by(x)))
     14 #define GUARDED_VAR         __attribute__ ((guarded_var))
     15 #define PT_GUARDED_BY(x)    __attribute__ ((pt_guarded_by(x)))
     16 #define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var))
     17 #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
     18 #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
     19 #define EXCLUSIVE_LOCK_FUNCTION(...)   __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
     20 #define SHARED_LOCK_FUNCTION(...)      __attribute__ ((shared_lock_function(__VA_ARGS__)))
     21 #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
     22 #define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__)))
     23 #define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__)))
     24 #define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x)))
     25 #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
     26 #define EXCLUSIVE_LOCKS_REQUIRED(...) \
     27   __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
     28 #define SHARED_LOCKS_REQUIRED(...) \
     29   __attribute__ ((shared_locks_required(__VA_ARGS__)))
     30 #define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
     31 
     32 
     33 class  __attribute__((lockable)) Mutex {
     34  public:
     35   void Lock() __attribute__((exclusive_lock_function));
     36   void ReaderLock() __attribute__((shared_lock_function));
     37   void Unlock() __attribute__((unlock_function));
     38   bool TryLock() __attribute__((exclusive_trylock_function(true)));
     39   bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
     40   void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
     41 };
     42 
     43 class __attribute__((scoped_lockable)) MutexLock {
     44  public:
     45   MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
     46   ~MutexLock() __attribute__((unlock_function));
     47 };
     48 
     49 class __attribute__((scoped_lockable)) ReaderMutexLock {
     50  public:
     51   ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
     52   ~ReaderMutexLock() __attribute__((unlock_function));
     53 };
     54 
     55 class SCOPED_LOCKABLE ReleasableMutexLock {
     56  public:
     57   ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
     58   ~ReleasableMutexLock() UNLOCK_FUNCTION();
     59 
     60   void Release() UNLOCK_FUNCTION();
     61 };
     62 
     63 
     64 // The universal lock, written "*", allows checking to be selectively turned
     65 // off for a particular piece of code.
     66 void beginNoWarnOnReads()  SHARED_LOCK_FUNCTION("*");
     67 void endNoWarnOnReads()    UNLOCK_FUNCTION("*");
     68 void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
     69 void endNoWarnOnWrites()   UNLOCK_FUNCTION("*");
     70 
     71 
     72 // For testing handling of smart pointers.
     73 template<class T>
     74 class SmartPtr {
     75 public:
     76   SmartPtr(T* p) : ptr_(p) { }
     77   SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
     78   ~SmartPtr();
     79 
     80   T* get()        const { return ptr_; }
     81   T* operator->() const { return ptr_; }
     82   T& operator*()  const { return *ptr_; }
     83 
     84 private:
     85   T* ptr_;
     86 };
     87 
     88 
     89 // For testing destructor calls and cleanup.
     90 class MyString {
     91 public:
     92   MyString(const char* s);
     93   ~MyString();
     94 };
     95 
     96 
     97 
     98 Mutex sls_mu;
     99 
    100 Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
    101 int sls_guard_var __attribute__((guarded_var)) = 0;
    102 int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
    103 
    104 bool getBool();
    105 
    106 class MutexWrapper {
    107 public:
    108    Mutex mu;
    109    int x __attribute__((guarded_by(mu)));
    110    void MyLock() __attribute__((exclusive_lock_function(mu)));
    111 };
    112 
    113 #else
    114 
    115 MutexWrapper sls_mw;
    116 
    117 void sls_fun_0() {
    118   sls_mw.mu.Lock();
    119   sls_mw.x = 5;
    120   sls_mw.mu.Unlock();
    121 }
    122 
    123 void sls_fun_2() {
    124   sls_mu.Lock();
    125   int x = sls_guard_var;
    126   sls_mu.Unlock();
    127 }
    128 
    129 void sls_fun_3() {
    130   sls_mu.Lock();
    131   sls_guard_var = 2;
    132   sls_mu.Unlock();
    133 }
    134 
    135 void sls_fun_4() {
    136   sls_mu2.Lock();
    137   sls_guard_var = 2;
    138   sls_mu2.Unlock();
    139 }
    140 
    141 void sls_fun_5() {
    142   sls_mu.Lock();
    143   int x = sls_guardby_var;
    144   sls_mu.Unlock();
    145 }
    146 
    147 void sls_fun_6() {
    148   sls_mu.Lock();
    149   sls_guardby_var = 2;
    150   sls_mu.Unlock();
    151 }
    152 
    153 void sls_fun_7() {
    154   sls_mu.Lock();
    155   sls_mu2.Lock();
    156   sls_mu2.Unlock();
    157   sls_mu.Unlock();
    158 }
    159 
    160 void sls_fun_8() {
    161   sls_mu.Lock();
    162   if (getBool())
    163     sls_mu.Unlock();
    164   else
    165     sls_mu.Unlock();
    166 }
    167 
    168 void sls_fun_9() {
    169   if (getBool())
    170     sls_mu.Lock();
    171   else
    172     sls_mu.Lock();
    173   sls_mu.Unlock();
    174 }
    175 
    176 void sls_fun_good_6() {
    177   if (getBool()) {
    178     sls_mu.Lock();
    179   } else {
    180     if (getBool()) {
    181       getBool(); // EMPTY
    182     } else {
    183       getBool(); // EMPTY
    184     }
    185     sls_mu.Lock();
    186   }
    187   sls_mu.Unlock();
    188 }
    189 
    190 void sls_fun_good_7() {
    191   sls_mu.Lock();
    192   while (getBool()) {
    193     sls_mu.Unlock();
    194     if (getBool()) {
    195       if (getBool()) {
    196         sls_mu.Lock();
    197         continue;
    198       }
    199     }
    200     sls_mu.Lock();
    201   }
    202   sls_mu.Unlock();
    203 }
    204 
    205 void sls_fun_good_8() {
    206   sls_mw.MyLock();
    207   sls_mw.mu.Unlock();
    208 }
    209 
    210 void sls_fun_bad_1() {
    211   sls_mu.Unlock(); // \
    212     // expected-warning{{releasing mutex 'sls_mu' that was not held}}
    213 }
    214 
    215 void sls_fun_bad_2() {
    216   sls_mu.Lock();
    217   sls_mu.Lock(); // \
    218     // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
    219   sls_mu.Unlock();
    220 }
    221 
    222 void sls_fun_bad_3() {
    223   sls_mu.Lock(); // expected-note {{mutex acquired here}}
    224 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
    225 
    226 void sls_fun_bad_4() {
    227   if (getBool())
    228     sls_mu.Lock();  // expected-note{{mutex acquired here}}
    229   else
    230     sls_mu2.Lock(); // expected-note{{mutex acquired here}}
    231 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}  \
    232   // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
    233 
    234 void sls_fun_bad_5() {
    235   sls_mu.Lock(); // expected-note {{mutex acquired here}}
    236   if (getBool())
    237     sls_mu.Unlock();
    238 } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
    239 
    240 void sls_fun_bad_6() {
    241   if (getBool()) {
    242     sls_mu.Lock(); // expected-note {{mutex acquired here}}
    243   } else {
    244     if (getBool()) {
    245       getBool(); // EMPTY
    246     } else {
    247       getBool(); // EMPTY
    248     }
    249   }
    250   sls_mu.Unlock(); // \
    251     expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
    252     expected-warning{{releasing mutex 'sls_mu' that was not held}}
    253 }
    254 
    255 void sls_fun_bad_7() {
    256   sls_mu.Lock();
    257   while (getBool()) {
    258     sls_mu.Unlock();
    259     if (getBool()) {
    260       if (getBool()) {
    261         continue; // \
    262         expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
    263       }
    264     }
    265     sls_mu.Lock(); // expected-note {{mutex acquired here}}
    266   }
    267   sls_mu.Unlock();
    268 }
    269 
    270 void sls_fun_bad_8() {
    271   sls_mu.Lock(); // expected-note{{mutex acquired here}}
    272 
    273   do {
    274     sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
    275   } while (getBool());
    276 }
    277 
    278 void sls_fun_bad_9() {
    279   do {
    280     sls_mu.Lock();  // \
    281       // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
    282       // expected-note{{mutex acquired here}}
    283   } while (getBool());
    284   sls_mu.Unlock();
    285 }
    286 
    287 void sls_fun_bad_10() {
    288   sls_mu.Lock();  // expected-note 2{{mutex acquired here}}
    289   while(getBool()) {  // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
    290     sls_mu.Unlock();
    291   }
    292 } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
    293 
    294 void sls_fun_bad_11() {
    295   while (getBool()) { // \
    296       expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
    297     sls_mu.Lock(); // expected-note {{mutex acquired here}}
    298   }
    299   sls_mu.Unlock(); // \
    300     // expected-warning{{releasing mutex 'sls_mu' that was not held}}
    301 }
    302 
    303 void sls_fun_bad_12() {
    304   sls_mu.Lock(); // expected-note {{mutex acquired here}}
    305   while (getBool()) {
    306     sls_mu.Unlock();
    307     if (getBool()) {
    308       if (getBool()) {
    309         break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
    310       }
    311     }
    312     sls_mu.Lock();
    313   }
    314   sls_mu.Unlock();
    315 }
    316 
    317 #endif
    318