brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.4 KiB · 549cb12 Raw
264 lines · c
1// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-pointer -Wthread-safety-beta %s2// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-pointer -Wthread-safety-beta -fexperimental-late-parse-attributes -DLATE_PARSING %s3 4#define LOCKABLE            __attribute__ ((lockable))5#define REENTRANT_CAPABILITY __attribute__ ((reentrant_capability))6#define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable))7#define GUARDED_BY(...)     __attribute__ ((guarded_by(__VA_ARGS__)))8#define GUARDED_VAR         __attribute__ ((guarded_var))9#define PT_GUARDED_BY(...)  __attribute__ ((pt_guarded_by(__VA_ARGS__)))10#define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var))11#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))12#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))13#define EXCLUSIVE_LOCK_FUNCTION(...)    __attribute__ ((exclusive_lock_function(__VA_ARGS__)))14#define SHARED_LOCK_FUNCTION(...)       __attribute__ ((shared_lock_function(__VA_ARGS__)))15#define ASSERT_EXCLUSIVE_LOCK(...)      __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))16#define ASSERT_SHARED_LOCK(...)         __attribute__ ((assert_shared_lock(__VA_ARGS__)))17#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))18#define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__)))19#define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__)))20#define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x)))21#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))22#define EXCLUSIVE_LOCKS_REQUIRED(...) \23  __attribute__ ((exclusive_locks_required(__VA_ARGS__)))24#define SHARED_LOCKS_REQUIRED(...) \25  __attribute__ ((shared_locks_required(__VA_ARGS__)))26#define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))27 28#define __READ_ONCE(x)        (*(const volatile __typeof__(x) *)&(x))29#define __WRITE_ONCE(x, val)  do { *(volatile __typeof__(x) *)&(x) = (val); } while (0)30 31// Define the mutex struct.32// Simplified only for test purpose.33struct LOCKABLE Mutex {};34 35struct Foo {36  struct Mutex *mu_;37  int  a_value GUARDED_BY(mu_);38 39  struct Bar {40    struct Mutex *other_mu ACQUIRED_AFTER(mu_); // Note: referencing the parent structure is convenient here, but this should probably be disallowed if the child structure is re-used outside of the parent.41    struct Mutex *third_mu ACQUIRED_BEFORE(other_mu);42  } bar;43 44  int* a_ptr PT_GUARDED_BY(bar.other_mu);45};46 47struct LOCKABLE Lock {};48struct A {49        struct Lock lock;50        union {51                int b __attribute__((guarded_by(lock))); // Note: referencing the parent structure is convenient here, but this should probably be disallowed if the child is re-used outside of the parent.52        };53};54 55// Declare mutex lock/unlock functions.56void mutex_exclusive_lock(struct Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);57void mutex_shared_lock(struct Mutex *mu) SHARED_LOCK_FUNCTION(mu);58void mutex_unlock(struct Mutex *mu) UNLOCK_FUNCTION(mu);59void mutex_shared_unlock(struct Mutex *mu) __attribute__((release_shared_capability(mu)));60void mutex_exclusive_unlock(struct Mutex *mu) __attribute__((release_capability(mu)));61 62// Define global variables.63struct Mutex mu1;64struct Mutex mu2 ACQUIRED_AFTER(mu1);65struct Foo foo_ = {&mu1};66int a_ GUARDED_BY(foo_.mu_);67int *b_ PT_GUARDED_BY(foo_.mu_) = &a_;68int c_ GUARDED_VAR;69int *d_ PT_GUARDED_VAR = &c_;70 71// Define test functions.72int Foo_fun1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {73  return i;74}75 76int Foo_fun2(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1) {77  return i;78}79 80int Foo_func3(int i) LOCKS_EXCLUDED(mu1, mu2) {81  return i;82}83 84static int Bar_fun1(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1) {85  return i;86}87 88void set_value(int *a, int value) EXCLUSIVE_LOCKS_REQUIRED(foo_.mu_) {89  *a = value;90}91 92int get_value(int *p) SHARED_LOCKS_REQUIRED(foo_.mu_){93  return *p;94}95 96void unlock_scope(struct Mutex *const *mu) __attribute__((release_capability(**mu)));97 98// Verify late parsing:99#ifdef LATE_PARSING100struct LateParsing {101  int a_value_defined_before GUARDED_BY(a_mutex_defined_late);102  int *a_ptr_defined_before PT_GUARDED_BY(a_mutex_defined_late);103  struct Mutex *a_mutex_defined_early104    ACQUIRED_BEFORE(a_mutex_defined_late);105  struct Mutex *a_mutex_defined_late106    ACQUIRED_AFTER(a_mutex_defined_very_late);107  struct Mutex *a_mutex_defined_very_late;108} late_parsing;109#endif110 111int main(void) {112 113  Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \114                  expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu1' exclusively}}115 116  mutex_exclusive_lock(&mu1); // expected-note{{mutex acquired here}}117  mutex_shared_lock(&mu2);118  Foo_fun1(1);119 120  mutex_shared_lock(&mu1); // expected-warning{{acquiring mutex 'mu1' that is already held}} \121                              expected-warning{{mutex 'mu1' must be acquired before 'mu2'}}122  mutex_unlock(&mu1);123  mutex_unlock(&mu2);124  mutex_shared_lock(&mu1);125  mutex_exclusive_lock(&mu2);126  Foo_fun2(2);127 128  mutex_unlock(&mu2);129  mutex_unlock(&mu1);130  mutex_exclusive_lock(&mu1);131  Bar_fun1(3);132  mutex_unlock(&mu1);133 134  mutex_exclusive_lock(&mu1);135  Foo_func3(4);  // expected-warning{{cannot call function 'Foo_func3' while mutex 'mu1' is held}}136  mutex_unlock(&mu1);137 138  Foo_func3(5);139 140  set_value(&a_, 0); // expected-warning{{calling function 'set_value' requires holding mutex 'foo_.mu_' exclusively}}141                     // expected-warning@-1{{passing pointer to variable 'a_' requires holding mutex 'foo_.mu_'}}142  get_value(b_); // expected-warning{{calling function 'get_value' requires holding mutex 'foo_.mu_'}}143                 // expected-warning@-1{{passing pointer 'b_' requires holding mutex 'foo_.mu_'}}144  mutex_exclusive_lock(foo_.mu_);145  set_value(&a_, 1);146  mutex_unlock(foo_.mu_);147  mutex_shared_lock(foo_.mu_);148  (void)(get_value(b_) == 1);149  mutex_unlock(foo_.mu_);150 151  a_ = 0; // expected-warning{{writing variable 'a_' requires holding mutex 'foo_.mu_'}}152  __WRITE_ONCE(a_, 0); // expected-warning{{writing variable 'a_' requires holding mutex 'foo_.mu_'}}153  (void)(a_ == 0); // expected-warning{{reading variable 'a_' requires holding mutex 'foo_.mu_'}}154  (void)(__READ_ONCE(a_) == 0); // expected-warning{{reading variable 'a_' requires holding mutex 'foo_.mu_'}}155  *b_ = 0; // expected-warning{{writing the value pointed to by 'b_' requires holding mutex 'foo_.mu_' exclusively}}156  __WRITE_ONCE(*b_, 0); // expected-warning{{writing the value pointed to by 'b_' requires holding mutex 'foo_.mu_' exclusively}}157  (void)(*b_ == 0); // expected-warning{{reading the value pointed to by 'b_' requires holding mutex 'foo_.mu_'}}158  (void)(__READ_ONCE(*b_) == 0); // expected-warning{{reading the value pointed to by 'b_' requires holding mutex 'foo_.mu_'}}159  c_ = 0; // expected-warning{{writing variable 'c_' requires holding any mutex exclusively}}160  (void)(*d_ == 0); // expected-warning{{reading the value pointed to by 'd_' requires holding any mutex}}161  mutex_exclusive_lock(foo_.mu_);162  a_ = 0;163  __WRITE_ONCE(a_, 0);164  (void)(a_ == 0);165  (void)(__READ_ONCE(a_) == 0);166  *b_ = 0;167  __WRITE_ONCE(*b_, 0);168  (void)(*b_ == 0);169  (void)(__READ_ONCE(*b_) == 0);170  c_ = 1;171  (void)(*d_ == 1);172  mutex_unlock(foo_.mu_);173 174  mutex_exclusive_lock(&mu1);    // expected-note {{mutex acquired here}}175  mutex_shared_unlock(&mu1);     // expected-warning {{releasing mutex 'mu1' using shared access, expected exclusive access}}176                                 // expected-note@-1{{mutex released here}}177  mutex_exclusive_unlock(&mu1);  // expected-warning {{releasing mutex 'mu1' that was not held}}178 179  mutex_shared_lock(&mu1);      // expected-note {{mutex acquired here}}180  mutex_exclusive_unlock(&mu1); // expected-warning {{releasing mutex 'mu1' using exclusive access, expected shared access}}181                                // expected-note@-1{{mutex released here}}182  mutex_shared_unlock(&mu1);    // expected-warning {{releasing mutex 'mu1' that was not held}}183 184  /// Cleanup functions185  {186    struct Mutex* const __attribute__((cleanup(unlock_scope))) scope = &mu1;187    mutex_exclusive_lock(scope);  // Lock through scope works.188    // Cleanup happens automatically -> no warning.189  }190  {191    struct Mutex* const __attribute__((unused, cleanup(unlock_scope))) scope = &mu1;192    mutex_exclusive_lock(&mu1);  // With basic alias analysis lock through mu1 also works.193  }194 195  foo_.a_value = 0; // expected-warning {{writing variable 'a_value' requires holding mutex 'mu_' exclusively}}196  *foo_.a_ptr = 1; // expected-warning {{writing the value pointed to by 'a_ptr' requires holding mutex 'bar.other_mu' exclusively}}197 198 199  mutex_exclusive_lock(foo_.bar.other_mu);200  mutex_exclusive_lock(foo_.bar.third_mu); // expected-warning{{mutex 'third_mu' must be acquired before 'other_mu'}}201  mutex_exclusive_lock(foo_.mu_); // expected-warning{{mutex 'mu_' must be acquired before 'other_mu'}}202  mutex_exclusive_unlock(foo_.mu_);203  mutex_exclusive_unlock(foo_.bar.other_mu);204  mutex_exclusive_unlock(foo_.bar.third_mu);205 206#ifdef LATE_PARSING207  late_parsing.a_value_defined_before = 1; // expected-warning{{writing variable 'a_value_defined_before' requires holding mutex 'a_mutex_defined_late' exclusively}}208  late_parsing.a_ptr_defined_before = 0;209  set_value(&late_parsing.a_value_defined_before, 0); // expected-warning{{calling function 'set_value' requires holding mutex 'foo_.mu_' exclusively}}210                                                      // expected-warning@-1{{passing pointer to variable 'a_value_defined_before' requires holding mutex 'a_mutex_defined_late'}}211  mutex_exclusive_lock(late_parsing.a_mutex_defined_late);212  mutex_exclusive_lock(late_parsing.a_mutex_defined_early); // expected-warning{{mutex 'a_mutex_defined_early' must be acquired before 'a_mutex_defined_late'}}213  mutex_exclusive_unlock(late_parsing.a_mutex_defined_early);214  mutex_exclusive_unlock(late_parsing.a_mutex_defined_late);215  mutex_exclusive_lock(late_parsing.a_mutex_defined_late);216  mutex_exclusive_lock(late_parsing.a_mutex_defined_very_late); // expected-warning{{mutex 'a_mutex_defined_very_late' must be acquired before 'a_mutex_defined_late'}}217  mutex_exclusive_unlock(late_parsing.a_mutex_defined_very_late);218  mutex_exclusive_unlock(late_parsing.a_mutex_defined_late);219#endif220 221  return 0;222}223 224/*** Reentrancy test ***/225struct LOCKABLE REENTRANT_CAPABILITY ReentrantMutex {};226void reentrant_mutex_lock(struct ReentrantMutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);227void reentrant_mutex_unlock(struct ReentrantMutex *mu) UNLOCK_FUNCTION(mu);228 229struct ReentrantMutex rmu;230int r_ GUARDED_BY(&rmu);231 232void test_reentrant(void) {233  reentrant_mutex_lock(&rmu);234  r_ = 1;235  reentrant_mutex_lock(&rmu);236  r_ = 1;237  reentrant_mutex_unlock(&rmu);238  r_ = 1;239  reentrant_mutex_unlock(&rmu);240  r_ = 1; // expected-warning{{writing variable 'r_' requires holding mutex 'rmu' exclusively}}241}242 243// We had a problem where we'd skip all attributes that follow a late-parsed244// attribute in a single __attribute__.245void run(void) __attribute__((guarded_by(mu1), guarded_by(mu1))); // expected-warning 2{{only applies to non-static data members and global variables}}246 247int value_with_wrong_number_of_args GUARDED_BY(mu1, mu2); // expected-error{{'guarded_by' attribute takes one argument}}248 249int *ptr_with_wrong_number_of_args PT_GUARDED_BY(mu1, mu2); // expected-error{{'pt_guarded_by' attribute takes one argument}}250 251int value_with_no_open_brace __attribute__((guarded_by)); // expected-error{{'guarded_by' attribute takes one argument}}252int *ptr_with_no_open_brace __attribute__((pt_guarded_by)); // expected-error{{'pt_guarded_by' attribute takes one argument}}253 254int value_with_no_open_brace_on_acquire_after __attribute__((acquired_after)); // expected-error{{'acquired_after' attribute takes at least 1 argument}}255int value_with_no_open_brace_on_acquire_before __attribute__((acquired_before)); // expected-error{{'acquired_before' attribute takes at least 1 argument}}256 257int value_with_bad_expr GUARDED_BY(bad_expr); // expected-error{{use of undeclared identifier 'bad_expr'}}258int *ptr_with_bad_expr PT_GUARDED_BY(bad_expr); // expected-error{{use of undeclared identifier 'bad_expr'}}259 260int value_with_bad_expr_on_acquire_after __attribute__((acquired_after(other_bad_expr))); //  expected-error{{use of undeclared identifier 'other_bad_expr'}}261int value_with_bad_expr_on_acquire_before __attribute__((acquired_before(other_bad_expr))); //  expected-error{{use of undeclared identifier 'other_bad_expr'}}262 263int a_final_expression = 0;264