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