1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s 2*f4a2713aSLionel Sambuc 3*f4a2713aSLionel Sambuc #define LOCKABLE __attribute__ ((lockable)) 4*f4a2713aSLionel Sambuc #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) 5*f4a2713aSLionel Sambuc #define GUARDED_BY(x) __attribute__ ((guarded_by(x))) 6*f4a2713aSLionel Sambuc #define GUARDED_VAR __attribute__ ((guarded_var)) 7*f4a2713aSLionel Sambuc #define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) 8*f4a2713aSLionel Sambuc #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) 9*f4a2713aSLionel Sambuc #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) 10*f4a2713aSLionel Sambuc #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) 11*f4a2713aSLionel Sambuc #define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) 12*f4a2713aSLionel Sambuc #define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) 13*f4a2713aSLionel Sambuc #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) 14*f4a2713aSLionel Sambuc #define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__))) 15*f4a2713aSLionel Sambuc #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) 16*f4a2713aSLionel Sambuc #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) 17*f4a2713aSLionel Sambuc #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) 18*f4a2713aSLionel Sambuc #define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) 19*f4a2713aSLionel Sambuc #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) 20*f4a2713aSLionel Sambuc #define EXCLUSIVE_LOCKS_REQUIRED(...) \ 21*f4a2713aSLionel Sambuc __attribute__ ((exclusive_locks_required(__VA_ARGS__))) 22*f4a2713aSLionel Sambuc #define SHARED_LOCKS_REQUIRED(...) \ 23*f4a2713aSLionel Sambuc __attribute__ ((shared_locks_required(__VA_ARGS__))) 24*f4a2713aSLionel Sambuc #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc 27*f4a2713aSLionel Sambuc class LOCKABLE Mutex { 28*f4a2713aSLionel Sambuc public: 29*f4a2713aSLionel Sambuc void Lock() EXCLUSIVE_LOCK_FUNCTION(); 30*f4a2713aSLionel Sambuc void ReaderLock() SHARED_LOCK_FUNCTION(); 31*f4a2713aSLionel Sambuc void Unlock() UNLOCK_FUNCTION(); 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); 34*f4a2713aSLionel Sambuc bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); 35*f4a2713aSLionel Sambuc 36*f4a2713aSLionel Sambuc void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); 37*f4a2713aSLionel Sambuc void AssertReaderHeld() ASSERT_SHARED_LOCK(); 38*f4a2713aSLionel Sambuc }; 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambuc class UnlockableMu{ 41*f4a2713aSLionel Sambuc }; 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc class MuWrapper { 44*f4a2713aSLionel Sambuc public: 45*f4a2713aSLionel Sambuc Mutex mu; 46*f4a2713aSLionel Sambuc Mutex getMu() { 47*f4a2713aSLionel Sambuc return mu; 48*f4a2713aSLionel Sambuc } 49*f4a2713aSLionel Sambuc Mutex * getMuPointer() { 50*f4a2713aSLionel Sambuc return μ 51*f4a2713aSLionel Sambuc } 52*f4a2713aSLionel Sambuc }; 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambuc 55*f4a2713aSLionel Sambuc class MuDoubleWrapper { 56*f4a2713aSLionel Sambuc public: 57*f4a2713aSLionel Sambuc MuWrapper* muWrapper; 58*f4a2713aSLionel Sambuc MuWrapper* getWrapper() { 59*f4a2713aSLionel Sambuc return muWrapper; 60*f4a2713aSLionel Sambuc } 61*f4a2713aSLionel Sambuc }; 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc Mutex mu1; 64*f4a2713aSLionel Sambuc UnlockableMu umu; 65*f4a2713aSLionel Sambuc Mutex mu2; 66*f4a2713aSLionel Sambuc MuWrapper muWrapper; 67*f4a2713aSLionel Sambuc MuDoubleWrapper muDoubleWrapper; 68*f4a2713aSLionel Sambuc Mutex* muPointer; 69*f4a2713aSLionel Sambuc Mutex** muDoublePointer = & muPointer; 70*f4a2713aSLionel Sambuc Mutex& muRef = mu1; 71*f4a2713aSLionel Sambuc 72*f4a2713aSLionel Sambuc //---------------------------------------// 73*f4a2713aSLionel Sambuc // Scoping tests 74*f4a2713aSLionel Sambuc //--------------------------------------// 75*f4a2713aSLionel Sambuc 76*f4a2713aSLionel Sambuc class Foo { 77*f4a2713aSLionel Sambuc Mutex foomu; 78*f4a2713aSLionel Sambuc void needLock() EXCLUSIVE_LOCK_FUNCTION(foomu); 79*f4a2713aSLionel Sambuc }; 80*f4a2713aSLionel Sambuc 81*f4a2713aSLionel Sambuc class Foo2 { 82*f4a2713aSLionel Sambuc void needLock() EXCLUSIVE_LOCK_FUNCTION(foomu); 83*f4a2713aSLionel Sambuc Mutex foomu; 84*f4a2713aSLionel Sambuc }; 85*f4a2713aSLionel Sambuc 86*f4a2713aSLionel Sambuc class Bar { 87*f4a2713aSLionel Sambuc Mutex barmu; 88*f4a2713aSLionel Sambuc Mutex barmu2 ACQUIRED_AFTER(barmu); 89*f4a2713aSLionel Sambuc }; 90*f4a2713aSLionel Sambuc 91*f4a2713aSLionel Sambuc 92*f4a2713aSLionel Sambuc //-----------------------------------------// 93*f4a2713aSLionel Sambuc // No Thread Safety Analysis (noanal) // 94*f4a2713aSLionel Sambuc //-----------------------------------------// 95*f4a2713aSLionel Sambuc 96*f4a2713aSLionel Sambuc // FIXME: Right now we cannot parse attributes put on function definitions 97*f4a2713aSLionel Sambuc // We would like to patch this at some point. 98*f4a2713aSLionel Sambuc 99*f4a2713aSLionel Sambuc #if !__has_attribute(no_thread_safety_analysis) 100*f4a2713aSLionel Sambuc #error "Should support no_thread_safety_analysis attribute" 101*f4a2713aSLionel Sambuc #endif 102*f4a2713aSLionel Sambuc 103*f4a2713aSLionel Sambuc void noanal_fun() NO_THREAD_SAFETY_ANALYSIS; 104*f4a2713aSLionel Sambuc 105*f4a2713aSLionel Sambuc void noanal_fun_args() __attribute__((no_thread_safety_analysis(1))); // \ 106*f4a2713aSLionel Sambuc // expected-error {{'no_thread_safety_analysis' attribute takes no arguments}} 107*f4a2713aSLionel Sambuc 108*f4a2713aSLionel Sambuc int noanal_testfn(int y) NO_THREAD_SAFETY_ANALYSIS; 109*f4a2713aSLionel Sambuc 110*f4a2713aSLionel Sambuc int noanal_testfn(int y) { 111*f4a2713aSLionel Sambuc int x NO_THREAD_SAFETY_ANALYSIS = y; // \ 112*f4a2713aSLionel Sambuc // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} 113*f4a2713aSLionel Sambuc return x; 114*f4a2713aSLionel Sambuc }; 115*f4a2713aSLionel Sambuc 116*f4a2713aSLionel Sambuc int noanal_test_var NO_THREAD_SAFETY_ANALYSIS; // \ 117*f4a2713aSLionel Sambuc // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} 118*f4a2713aSLionel Sambuc 119*f4a2713aSLionel Sambuc class NoanalFoo { 120*f4a2713aSLionel Sambuc private: 121*f4a2713aSLionel Sambuc int test_field NO_THREAD_SAFETY_ANALYSIS; // \ 122*f4a2713aSLionel Sambuc // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} 123*f4a2713aSLionel Sambuc void test_method() NO_THREAD_SAFETY_ANALYSIS; 124*f4a2713aSLionel Sambuc }; 125*f4a2713aSLionel Sambuc 126*f4a2713aSLionel Sambuc class NO_THREAD_SAFETY_ANALYSIS NoanalTestClass { // \ 127*f4a2713aSLionel Sambuc // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} 128*f4a2713aSLionel Sambuc }; 129*f4a2713aSLionel Sambuc 130*f4a2713aSLionel Sambuc void noanal_fun_params(int lvar NO_THREAD_SAFETY_ANALYSIS); // \ 131*f4a2713aSLionel Sambuc // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc 134*f4a2713aSLionel Sambuc //-----------------------------------------// 135*f4a2713aSLionel Sambuc // Guarded Var Attribute (gv) 136*f4a2713aSLionel Sambuc //-----------------------------------------// 137*f4a2713aSLionel Sambuc 138*f4a2713aSLionel Sambuc #if !__has_attribute(guarded_var) 139*f4a2713aSLionel Sambuc #error "Should support guarded_var attribute" 140*f4a2713aSLionel Sambuc #endif 141*f4a2713aSLionel Sambuc 142*f4a2713aSLionel Sambuc int gv_var_noargs GUARDED_VAR; 143*f4a2713aSLionel Sambuc 144*f4a2713aSLionel Sambuc int gv_var_args __attribute__((guarded_var(1))); // \ 145*f4a2713aSLionel Sambuc // expected-error {{'guarded_var' attribute takes no arguments}} 146*f4a2713aSLionel Sambuc 147*f4a2713aSLionel Sambuc class GVFoo { 148*f4a2713aSLionel Sambuc private: 149*f4a2713aSLionel Sambuc int gv_field_noargs GUARDED_VAR; 150*f4a2713aSLionel Sambuc int gv_field_args __attribute__((guarded_var(1))); // \ 151*f4a2713aSLionel Sambuc // expected-error {{'guarded_var' attribute takes no arguments}} 152*f4a2713aSLionel Sambuc }; 153*f4a2713aSLionel Sambuc 154*f4a2713aSLionel Sambuc class GUARDED_VAR GV { // \ 155*f4a2713aSLionel Sambuc // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} 156*f4a2713aSLionel Sambuc }; 157*f4a2713aSLionel Sambuc 158*f4a2713aSLionel Sambuc void gv_function() GUARDED_VAR; // \ 159*f4a2713aSLionel Sambuc // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} 160*f4a2713aSLionel Sambuc 161*f4a2713aSLionel Sambuc void gv_function_params(int gv_lvar GUARDED_VAR); // \ 162*f4a2713aSLionel Sambuc // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc int gv_testfn(int y){ 165*f4a2713aSLionel Sambuc int x GUARDED_VAR = y; // \ 166*f4a2713aSLionel Sambuc // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} 167*f4a2713aSLionel Sambuc return x; 168*f4a2713aSLionel Sambuc } 169*f4a2713aSLionel Sambuc 170*f4a2713aSLionel Sambuc //-----------------------------------------// 171*f4a2713aSLionel Sambuc // Pt Guarded Var Attribute (pgv) 172*f4a2713aSLionel Sambuc //-----------------------------------------// 173*f4a2713aSLionel Sambuc 174*f4a2713aSLionel Sambuc //FIXME: add support for boost::scoped_ptr<int> fancyptr and references 175*f4a2713aSLionel Sambuc 176*f4a2713aSLionel Sambuc #if !__has_attribute(pt_guarded_var) 177*f4a2713aSLionel Sambuc #error "Should support pt_guarded_var attribute" 178*f4a2713aSLionel Sambuc #endif 179*f4a2713aSLionel Sambuc 180*f4a2713aSLionel Sambuc int *pgv_pt_var_noargs PT_GUARDED_VAR; 181*f4a2713aSLionel Sambuc 182*f4a2713aSLionel Sambuc int pgv_var_noargs PT_GUARDED_VAR; // \ 183*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} 184*f4a2713aSLionel Sambuc 185*f4a2713aSLionel Sambuc class PGVFoo { 186*f4a2713aSLionel Sambuc private: 187*f4a2713aSLionel Sambuc int *pt_field_noargs PT_GUARDED_VAR; 188*f4a2713aSLionel Sambuc int field_noargs PT_GUARDED_VAR; // \ 189*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} 190*f4a2713aSLionel Sambuc int *gv_field_args __attribute__((pt_guarded_var(1))); // \ 191*f4a2713aSLionel Sambuc // expected-error {{'pt_guarded_var' attribute takes no arguments}} 192*f4a2713aSLionel Sambuc }; 193*f4a2713aSLionel Sambuc 194*f4a2713aSLionel Sambuc class PT_GUARDED_VAR PGV { // \ 195*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} 196*f4a2713aSLionel Sambuc }; 197*f4a2713aSLionel Sambuc 198*f4a2713aSLionel Sambuc int *pgv_var_args __attribute__((pt_guarded_var(1))); // \ 199*f4a2713aSLionel Sambuc // expected-error {{'pt_guarded_var' attribute takes no arguments}} 200*f4a2713aSLionel Sambuc 201*f4a2713aSLionel Sambuc 202*f4a2713aSLionel Sambuc void pgv_function() PT_GUARDED_VAR; // \ 203*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} 204*f4a2713aSLionel Sambuc 205*f4a2713aSLionel Sambuc void pgv_function_params(int *gv_lvar PT_GUARDED_VAR); // \ 206*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} 207*f4a2713aSLionel Sambuc 208*f4a2713aSLionel Sambuc void pgv_testfn(int y){ 209*f4a2713aSLionel Sambuc int *x PT_GUARDED_VAR = new int(0); // \ 210*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} 211*f4a2713aSLionel Sambuc delete x; 212*f4a2713aSLionel Sambuc } 213*f4a2713aSLionel Sambuc 214*f4a2713aSLionel Sambuc //-----------------------------------------// 215*f4a2713aSLionel Sambuc // Lockable Attribute (l) 216*f4a2713aSLionel Sambuc //-----------------------------------------// 217*f4a2713aSLionel Sambuc 218*f4a2713aSLionel Sambuc //FIXME: In future we may want to add support for structs, ObjC classes, etc. 219*f4a2713aSLionel Sambuc 220*f4a2713aSLionel Sambuc #if !__has_attribute(lockable) 221*f4a2713aSLionel Sambuc #error "Should support lockable attribute" 222*f4a2713aSLionel Sambuc #endif 223*f4a2713aSLionel Sambuc 224*f4a2713aSLionel Sambuc class LOCKABLE LTestClass { 225*f4a2713aSLionel Sambuc }; 226*f4a2713aSLionel Sambuc 227*f4a2713aSLionel Sambuc class __attribute__((lockable (1))) LTestClass_args { // \ 228*f4a2713aSLionel Sambuc // expected-error {{'lockable' attribute takes no arguments}} 229*f4a2713aSLionel Sambuc }; 230*f4a2713aSLionel Sambuc 231*f4a2713aSLionel Sambuc void l_test_function() LOCKABLE; // \ 232*f4a2713aSLionel Sambuc // expected-warning {{'lockable' attribute only applies to classes}} 233*f4a2713aSLionel Sambuc 234*f4a2713aSLionel Sambuc int l_testfn(int y) { 235*f4a2713aSLionel Sambuc int x LOCKABLE = y; // \ 236*f4a2713aSLionel Sambuc // expected-warning {{'lockable' attribute only applies to classes}} 237*f4a2713aSLionel Sambuc return x; 238*f4a2713aSLionel Sambuc } 239*f4a2713aSLionel Sambuc 240*f4a2713aSLionel Sambuc int l_test_var LOCKABLE; // \ 241*f4a2713aSLionel Sambuc // expected-warning {{'lockable' attribute only applies to classes}} 242*f4a2713aSLionel Sambuc 243*f4a2713aSLionel Sambuc class LFoo { 244*f4a2713aSLionel Sambuc private: 245*f4a2713aSLionel Sambuc int test_field LOCKABLE; // \ 246*f4a2713aSLionel Sambuc // expected-warning {{'lockable' attribute only applies to classes}} 247*f4a2713aSLionel Sambuc void test_method() LOCKABLE; // \ 248*f4a2713aSLionel Sambuc // expected-warning {{'lockable' attribute only applies to classes}} 249*f4a2713aSLionel Sambuc }; 250*f4a2713aSLionel Sambuc 251*f4a2713aSLionel Sambuc 252*f4a2713aSLionel Sambuc void l_function_params(int lvar LOCKABLE); // \ 253*f4a2713aSLionel Sambuc // expected-warning {{'lockable' attribute only applies to classes}} 254*f4a2713aSLionel Sambuc 255*f4a2713aSLionel Sambuc 256*f4a2713aSLionel Sambuc //-----------------------------------------// 257*f4a2713aSLionel Sambuc // Scoped Lockable Attribute (sl) 258*f4a2713aSLionel Sambuc //-----------------------------------------// 259*f4a2713aSLionel Sambuc 260*f4a2713aSLionel Sambuc #if !__has_attribute(scoped_lockable) 261*f4a2713aSLionel Sambuc #error "Should support scoped_lockable attribute" 262*f4a2713aSLionel Sambuc #endif 263*f4a2713aSLionel Sambuc 264*f4a2713aSLionel Sambuc class SCOPED_LOCKABLE SLTestClass { 265*f4a2713aSLionel Sambuc }; 266*f4a2713aSLionel Sambuc 267*f4a2713aSLionel Sambuc class __attribute__((scoped_lockable (1))) SLTestClass_args { // \ 268*f4a2713aSLionel Sambuc // expected-error {{'scoped_lockable' attribute takes no arguments}} 269*f4a2713aSLionel Sambuc }; 270*f4a2713aSLionel Sambuc 271*f4a2713aSLionel Sambuc void sl_test_function() SCOPED_LOCKABLE; // \ 272*f4a2713aSLionel Sambuc // expected-warning {{'scoped_lockable' attribute only applies to classes}} 273*f4a2713aSLionel Sambuc 274*f4a2713aSLionel Sambuc int sl_testfn(int y) { 275*f4a2713aSLionel Sambuc int x SCOPED_LOCKABLE = y; // \ 276*f4a2713aSLionel Sambuc // expected-warning {{'scoped_lockable' attribute only applies to classes}} 277*f4a2713aSLionel Sambuc return x; 278*f4a2713aSLionel Sambuc } 279*f4a2713aSLionel Sambuc 280*f4a2713aSLionel Sambuc int sl_test_var SCOPED_LOCKABLE; // \ 281*f4a2713aSLionel Sambuc // expected-warning {{'scoped_lockable' attribute only applies to classes}} 282*f4a2713aSLionel Sambuc 283*f4a2713aSLionel Sambuc class SLFoo { 284*f4a2713aSLionel Sambuc private: 285*f4a2713aSLionel Sambuc int test_field SCOPED_LOCKABLE; // \ 286*f4a2713aSLionel Sambuc // expected-warning {{'scoped_lockable' attribute only applies to classes}} 287*f4a2713aSLionel Sambuc void test_method() SCOPED_LOCKABLE; // \ 288*f4a2713aSLionel Sambuc // expected-warning {{'scoped_lockable' attribute only applies to classes}} 289*f4a2713aSLionel Sambuc }; 290*f4a2713aSLionel Sambuc 291*f4a2713aSLionel Sambuc 292*f4a2713aSLionel Sambuc void sl_function_params(int lvar SCOPED_LOCKABLE); // \ 293*f4a2713aSLionel Sambuc // expected-warning {{'scoped_lockable' attribute only applies to classes}} 294*f4a2713aSLionel Sambuc 295*f4a2713aSLionel Sambuc 296*f4a2713aSLionel Sambuc //-----------------------------------------// 297*f4a2713aSLionel Sambuc // Guarded By Attribute (gb) 298*f4a2713aSLionel Sambuc //-----------------------------------------// 299*f4a2713aSLionel Sambuc 300*f4a2713aSLionel Sambuc // FIXME: Eventually, would we like this attribute to take more than 1 arg? 301*f4a2713aSLionel Sambuc 302*f4a2713aSLionel Sambuc #if !__has_attribute(guarded_by) 303*f4a2713aSLionel Sambuc #error "Should support guarded_by attribute" 304*f4a2713aSLionel Sambuc #endif 305*f4a2713aSLionel Sambuc 306*f4a2713aSLionel Sambuc //1. Check applied to the right types & argument number 307*f4a2713aSLionel Sambuc 308*f4a2713aSLionel Sambuc int gb_var_arg GUARDED_BY(mu1); 309*f4a2713aSLionel Sambuc 310*f4a2713aSLionel Sambuc int gb_non_ascii GUARDED_BY(L"wide"); // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} 311*f4a2713aSLionel Sambuc 312*f4a2713aSLionel Sambuc int gb_var_args __attribute__((guarded_by(mu1, mu2))); // \ 313*f4a2713aSLionel Sambuc // expected-error {{'guarded_by' attribute takes one argument}} 314*f4a2713aSLionel Sambuc 315*f4a2713aSLionel Sambuc int gb_var_noargs __attribute__((guarded_by)); // \ 316*f4a2713aSLionel Sambuc // expected-error {{'guarded_by' attribute takes one argument}} 317*f4a2713aSLionel Sambuc 318*f4a2713aSLionel Sambuc class GBFoo { 319*f4a2713aSLionel Sambuc private: 320*f4a2713aSLionel Sambuc int gb_field_noargs __attribute__((guarded_by)); // \ 321*f4a2713aSLionel Sambuc // expected-error {{'guarded_by' attribute takes one argument}} 322*f4a2713aSLionel Sambuc int gb_field_args GUARDED_BY(mu1); 323*f4a2713aSLionel Sambuc }; 324*f4a2713aSLionel Sambuc 325*f4a2713aSLionel Sambuc class GUARDED_BY(mu1) GB { // \ 326*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} 327*f4a2713aSLionel Sambuc }; 328*f4a2713aSLionel Sambuc 329*f4a2713aSLionel Sambuc void gb_function() GUARDED_BY(mu1); // \ 330*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} 331*f4a2713aSLionel Sambuc 332*f4a2713aSLionel Sambuc void gb_function_params(int gv_lvar GUARDED_BY(mu1)); // \ 333*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} 334*f4a2713aSLionel Sambuc 335*f4a2713aSLionel Sambuc int gb_testfn(int y){ 336*f4a2713aSLionel Sambuc int x GUARDED_BY(mu1) = y; // \ 337*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} 338*f4a2713aSLionel Sambuc return x; 339*f4a2713aSLionel Sambuc } 340*f4a2713aSLionel Sambuc 341*f4a2713aSLionel Sambuc //2. Check argument parsing. 342*f4a2713aSLionel Sambuc 343*f4a2713aSLionel Sambuc // legal attribute arguments 344*f4a2713aSLionel Sambuc int gb_var_arg_1 GUARDED_BY(muWrapper.mu); 345*f4a2713aSLionel Sambuc int gb_var_arg_2 GUARDED_BY(muDoubleWrapper.muWrapper->mu); 346*f4a2713aSLionel Sambuc int gb_var_arg_3 GUARDED_BY(muWrapper.getMu()); 347*f4a2713aSLionel Sambuc int gb_var_arg_4 GUARDED_BY(*muWrapper.getMuPointer()); 348*f4a2713aSLionel Sambuc int gb_var_arg_5 GUARDED_BY(&mu1); 349*f4a2713aSLionel Sambuc int gb_var_arg_6 GUARDED_BY(muRef); 350*f4a2713aSLionel Sambuc int gb_var_arg_7 GUARDED_BY(muDoubleWrapper.getWrapper()->getMu()); 351*f4a2713aSLionel Sambuc int gb_var_arg_8 GUARDED_BY(muPointer); 352*f4a2713aSLionel Sambuc 353*f4a2713aSLionel Sambuc 354*f4a2713aSLionel Sambuc // illegal attribute arguments 355*f4a2713aSLionel Sambuc int gb_var_arg_bad_1 GUARDED_BY(1); // \ 356*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}} 357*f4a2713aSLionel Sambuc int gb_var_arg_bad_2 GUARDED_BY("mu"); // \ 358*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} 359*f4a2713aSLionel Sambuc int gb_var_arg_bad_3 GUARDED_BY(muDoublePointer); // \ 360*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mutex **'}} 361*f4a2713aSLionel Sambuc int gb_var_arg_bad_4 GUARDED_BY(umu); // \ 362*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}} 363*f4a2713aSLionel Sambuc 364*f4a2713aSLionel Sambuc //3. 365*f4a2713aSLionel Sambuc // Thread Safety analysis tests 366*f4a2713aSLionel Sambuc 367*f4a2713aSLionel Sambuc 368*f4a2713aSLionel Sambuc //-----------------------------------------// 369*f4a2713aSLionel Sambuc // Pt Guarded By Attribute (pgb) 370*f4a2713aSLionel Sambuc //-----------------------------------------// 371*f4a2713aSLionel Sambuc 372*f4a2713aSLionel Sambuc #if !__has_attribute(pt_guarded_by) 373*f4a2713aSLionel Sambuc #error "Should support pt_guarded_by attribute" 374*f4a2713aSLionel Sambuc #endif 375*f4a2713aSLionel Sambuc 376*f4a2713aSLionel Sambuc //1. Check applied to the right types & argument number 377*f4a2713aSLionel Sambuc 378*f4a2713aSLionel Sambuc int *pgb_var_noargs __attribute__((pt_guarded_by)); // \ 379*f4a2713aSLionel Sambuc // expected-error {{'pt_guarded_by' attribute takes one argument}} 380*f4a2713aSLionel Sambuc 381*f4a2713aSLionel Sambuc int *pgb_ptr_var_arg PT_GUARDED_BY(mu1); 382*f4a2713aSLionel Sambuc 383*f4a2713aSLionel Sambuc int *pgb_ptr_var_args __attribute__((pt_guarded_by(mu1, mu2))); // \ 384*f4a2713aSLionel Sambuc // expected-error {{'pt_guarded_by' attribute takes one argument}} 385*f4a2713aSLionel Sambuc 386*f4a2713aSLionel Sambuc int pgb_var_args PT_GUARDED_BY(mu1); // \ 387*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}} 388*f4a2713aSLionel Sambuc 389*f4a2713aSLionel Sambuc class PGBFoo { 390*f4a2713aSLionel Sambuc private: 391*f4a2713aSLionel Sambuc int *pgb_field_noargs __attribute__((pt_guarded_by)); // \ 392*f4a2713aSLionel Sambuc // expected-error {{'pt_guarded_by' attribute takes one argument}} 393*f4a2713aSLionel Sambuc int *pgb_field_args PT_GUARDED_BY(mu1); 394*f4a2713aSLionel Sambuc }; 395*f4a2713aSLionel Sambuc 396*f4a2713aSLionel Sambuc class PT_GUARDED_BY(mu1) PGB { // \ 397*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} 398*f4a2713aSLionel Sambuc }; 399*f4a2713aSLionel Sambuc 400*f4a2713aSLionel Sambuc void pgb_function() PT_GUARDED_BY(mu1); // \ 401*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} 402*f4a2713aSLionel Sambuc 403*f4a2713aSLionel Sambuc void pgb_function_params(int gv_lvar PT_GUARDED_BY(mu1)); // \ 404*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} 405*f4a2713aSLionel Sambuc 406*f4a2713aSLionel Sambuc void pgb_testfn(int y){ 407*f4a2713aSLionel Sambuc int *x PT_GUARDED_BY(mu1) = new int(0); // \ 408*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} 409*f4a2713aSLionel Sambuc delete x; 410*f4a2713aSLionel Sambuc } 411*f4a2713aSLionel Sambuc 412*f4a2713aSLionel Sambuc //2. Check argument parsing. 413*f4a2713aSLionel Sambuc 414*f4a2713aSLionel Sambuc // legal attribute arguments 415*f4a2713aSLionel Sambuc int * pgb_var_arg_1 PT_GUARDED_BY(muWrapper.mu); 416*f4a2713aSLionel Sambuc int * pgb_var_arg_2 PT_GUARDED_BY(muDoubleWrapper.muWrapper->mu); 417*f4a2713aSLionel Sambuc int * pgb_var_arg_3 PT_GUARDED_BY(muWrapper.getMu()); 418*f4a2713aSLionel Sambuc int * pgb_var_arg_4 PT_GUARDED_BY(*muWrapper.getMuPointer()); 419*f4a2713aSLionel Sambuc int * pgb_var_arg_5 PT_GUARDED_BY(&mu1); 420*f4a2713aSLionel Sambuc int * pgb_var_arg_6 PT_GUARDED_BY(muRef); 421*f4a2713aSLionel Sambuc int * pgb_var_arg_7 PT_GUARDED_BY(muDoubleWrapper.getWrapper()->getMu()); 422*f4a2713aSLionel Sambuc int * pgb_var_arg_8 PT_GUARDED_BY(muPointer); 423*f4a2713aSLionel Sambuc 424*f4a2713aSLionel Sambuc 425*f4a2713aSLionel Sambuc // illegal attribute arguments 426*f4a2713aSLionel Sambuc int * pgb_var_arg_bad_1 PT_GUARDED_BY(1); // \ 427*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} 428*f4a2713aSLionel Sambuc int * pgb_var_arg_bad_2 PT_GUARDED_BY("mu"); // \ 429*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'pt_guarded_by' attribute because its argument is invalid}} 430*f4a2713aSLionel Sambuc int * pgb_var_arg_bad_3 PT_GUARDED_BY(muDoublePointer); // \ 431*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} 432*f4a2713aSLionel Sambuc int * pgb_var_arg_bad_4 PT_GUARDED_BY(umu); // \ 433*f4a2713aSLionel Sambuc // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} 434*f4a2713aSLionel Sambuc 435*f4a2713aSLionel Sambuc 436*f4a2713aSLionel Sambuc //-----------------------------------------// 437*f4a2713aSLionel Sambuc // Acquired After (aa) 438*f4a2713aSLionel Sambuc //-----------------------------------------// 439*f4a2713aSLionel Sambuc 440*f4a2713aSLionel Sambuc // FIXME: Would we like this attribute to take more than 1 arg? 441*f4a2713aSLionel Sambuc 442*f4a2713aSLionel Sambuc #if !__has_attribute(acquired_after) 443*f4a2713aSLionel Sambuc #error "Should support acquired_after attribute" 444*f4a2713aSLionel Sambuc #endif 445*f4a2713aSLionel Sambuc 446*f4a2713aSLionel Sambuc Mutex mu_aa ACQUIRED_AFTER(mu1); 447*f4a2713aSLionel Sambuc 448*f4a2713aSLionel Sambuc Mutex aa_var_noargs __attribute__((acquired_after)); // \ 449*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 450*f4a2713aSLionel Sambuc 451*f4a2713aSLionel Sambuc class AAFoo { 452*f4a2713aSLionel Sambuc private: 453*f4a2713aSLionel Sambuc Mutex aa_field_noargs __attribute__((acquired_after)); // \ 454*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 455*f4a2713aSLionel Sambuc Mutex aa_field_args ACQUIRED_AFTER(mu1); 456*f4a2713aSLionel Sambuc }; 457*f4a2713aSLionel Sambuc 458*f4a2713aSLionel Sambuc class ACQUIRED_AFTER(mu1) AA { // \ 459*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} 460*f4a2713aSLionel Sambuc }; 461*f4a2713aSLionel Sambuc 462*f4a2713aSLionel Sambuc void aa_function() ACQUIRED_AFTER(mu1); // \ 463*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} 464*f4a2713aSLionel Sambuc 465*f4a2713aSLionel Sambuc void aa_function_params(int gv_lvar ACQUIRED_AFTER(mu1)); // \ 466*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} 467*f4a2713aSLionel Sambuc 468*f4a2713aSLionel Sambuc void aa_testfn(int y){ 469*f4a2713aSLionel Sambuc Mutex x ACQUIRED_AFTER(mu1) = Mutex(); // \ 470*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} 471*f4a2713aSLionel Sambuc } 472*f4a2713aSLionel Sambuc 473*f4a2713aSLionel Sambuc //Check argument parsing. 474*f4a2713aSLionel Sambuc 475*f4a2713aSLionel Sambuc // legal attribute arguments 476*f4a2713aSLionel Sambuc Mutex aa_var_arg_1 ACQUIRED_AFTER(muWrapper.mu); 477*f4a2713aSLionel Sambuc Mutex aa_var_arg_2 ACQUIRED_AFTER(muDoubleWrapper.muWrapper->mu); 478*f4a2713aSLionel Sambuc Mutex aa_var_arg_3 ACQUIRED_AFTER(muWrapper.getMu()); 479*f4a2713aSLionel Sambuc Mutex aa_var_arg_4 ACQUIRED_AFTER(*muWrapper.getMuPointer()); 480*f4a2713aSLionel Sambuc Mutex aa_var_arg_5 ACQUIRED_AFTER(&mu1); 481*f4a2713aSLionel Sambuc Mutex aa_var_arg_6 ACQUIRED_AFTER(muRef); 482*f4a2713aSLionel Sambuc Mutex aa_var_arg_7 ACQUIRED_AFTER(muDoubleWrapper.getWrapper()->getMu()); 483*f4a2713aSLionel Sambuc Mutex aa_var_arg_8 ACQUIRED_AFTER(muPointer); 484*f4a2713aSLionel Sambuc 485*f4a2713aSLionel Sambuc 486*f4a2713aSLionel Sambuc // illegal attribute arguments 487*f4a2713aSLionel Sambuc Mutex aa_var_arg_bad_1 ACQUIRED_AFTER(1); // \ 488*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} 489*f4a2713aSLionel Sambuc Mutex aa_var_arg_bad_2 ACQUIRED_AFTER("mu"); // \ 490*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'acquired_after' attribute because its argument is invalid}} 491*f4a2713aSLionel Sambuc Mutex aa_var_arg_bad_3 ACQUIRED_AFTER(muDoublePointer); // \ 492*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} 493*f4a2713aSLionel Sambuc Mutex aa_var_arg_bad_4 ACQUIRED_AFTER(umu); // \ 494*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} 495*f4a2713aSLionel Sambuc UnlockableMu aa_var_arg_bad_5 ACQUIRED_AFTER(mu_aa); // \ 496*f4a2713aSLionel Sambuc // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}} 497*f4a2713aSLionel Sambuc 498*f4a2713aSLionel Sambuc //-----------------------------------------// 499*f4a2713aSLionel Sambuc // Acquired Before (ab) 500*f4a2713aSLionel Sambuc //-----------------------------------------// 501*f4a2713aSLionel Sambuc 502*f4a2713aSLionel Sambuc #if !__has_attribute(acquired_before) 503*f4a2713aSLionel Sambuc #error "Should support acquired_before attribute" 504*f4a2713aSLionel Sambuc #endif 505*f4a2713aSLionel Sambuc 506*f4a2713aSLionel Sambuc Mutex mu_ab ACQUIRED_BEFORE(mu1); 507*f4a2713aSLionel Sambuc 508*f4a2713aSLionel Sambuc Mutex ab_var_noargs __attribute__((acquired_before)); // \ 509*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 510*f4a2713aSLionel Sambuc 511*f4a2713aSLionel Sambuc class ABFoo { 512*f4a2713aSLionel Sambuc private: 513*f4a2713aSLionel Sambuc Mutex ab_field_noargs __attribute__((acquired_before)); // \ 514*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 515*f4a2713aSLionel Sambuc Mutex ab_field_args ACQUIRED_BEFORE(mu1); 516*f4a2713aSLionel Sambuc }; 517*f4a2713aSLionel Sambuc 518*f4a2713aSLionel Sambuc class ACQUIRED_BEFORE(mu1) AB { // \ 519*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} 520*f4a2713aSLionel Sambuc }; 521*f4a2713aSLionel Sambuc 522*f4a2713aSLionel Sambuc void ab_function() ACQUIRED_BEFORE(mu1); // \ 523*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} 524*f4a2713aSLionel Sambuc 525*f4a2713aSLionel Sambuc void ab_function_params(int gv_lvar ACQUIRED_BEFORE(mu1)); // \ 526*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} 527*f4a2713aSLionel Sambuc 528*f4a2713aSLionel Sambuc void ab_testfn(int y){ 529*f4a2713aSLionel Sambuc Mutex x ACQUIRED_BEFORE(mu1) = Mutex(); // \ 530*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} 531*f4a2713aSLionel Sambuc } 532*f4a2713aSLionel Sambuc 533*f4a2713aSLionel Sambuc // Note: illegal int ab_int ACQUIRED_BEFORE(mu1) will 534*f4a2713aSLionel Sambuc // be taken care of by warnings that ab__int is not lockable. 535*f4a2713aSLionel Sambuc 536*f4a2713aSLionel Sambuc //Check argument parsing. 537*f4a2713aSLionel Sambuc 538*f4a2713aSLionel Sambuc // legal attribute arguments 539*f4a2713aSLionel Sambuc Mutex ab_var_arg_1 ACQUIRED_BEFORE(muWrapper.mu); 540*f4a2713aSLionel Sambuc Mutex ab_var_arg_2 ACQUIRED_BEFORE(muDoubleWrapper.muWrapper->mu); 541*f4a2713aSLionel Sambuc Mutex ab_var_arg_3 ACQUIRED_BEFORE(muWrapper.getMu()); 542*f4a2713aSLionel Sambuc Mutex ab_var_arg_4 ACQUIRED_BEFORE(*muWrapper.getMuPointer()); 543*f4a2713aSLionel Sambuc Mutex ab_var_arg_5 ACQUIRED_BEFORE(&mu1); 544*f4a2713aSLionel Sambuc Mutex ab_var_arg_6 ACQUIRED_BEFORE(muRef); 545*f4a2713aSLionel Sambuc Mutex ab_var_arg_7 ACQUIRED_BEFORE(muDoubleWrapper.getWrapper()->getMu()); 546*f4a2713aSLionel Sambuc Mutex ab_var_arg_8 ACQUIRED_BEFORE(muPointer); 547*f4a2713aSLionel Sambuc 548*f4a2713aSLionel Sambuc 549*f4a2713aSLionel Sambuc // illegal attribute arguments 550*f4a2713aSLionel Sambuc Mutex ab_var_arg_bad_1 ACQUIRED_BEFORE(1); // \ 551*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} 552*f4a2713aSLionel Sambuc Mutex ab_var_arg_bad_2 ACQUIRED_BEFORE("mu"); // \ 553*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'acquired_before' attribute because its argument is invalid}} 554*f4a2713aSLionel Sambuc Mutex ab_var_arg_bad_3 ACQUIRED_BEFORE(muDoublePointer); // \ 555*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} 556*f4a2713aSLionel Sambuc Mutex ab_var_arg_bad_4 ACQUIRED_BEFORE(umu); // \ 557*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} 558*f4a2713aSLionel Sambuc UnlockableMu ab_var_arg_bad_5 ACQUIRED_BEFORE(mu_ab); // \ 559*f4a2713aSLionel Sambuc // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}} 560*f4a2713aSLionel Sambuc 561*f4a2713aSLionel Sambuc 562*f4a2713aSLionel Sambuc //-----------------------------------------// 563*f4a2713aSLionel Sambuc // Exclusive Lock Function (elf) 564*f4a2713aSLionel Sambuc //-----------------------------------------// 565*f4a2713aSLionel Sambuc 566*f4a2713aSLionel Sambuc #if !__has_attribute(exclusive_lock_function) 567*f4a2713aSLionel Sambuc #error "Should support exclusive_lock_function attribute" 568*f4a2713aSLionel Sambuc #endif 569*f4a2713aSLionel Sambuc 570*f4a2713aSLionel Sambuc // takes zero or more arguments, all locks (vars/fields) 571*f4a2713aSLionel Sambuc 572*f4a2713aSLionel Sambuc void elf_function() EXCLUSIVE_LOCK_FUNCTION(); 573*f4a2713aSLionel Sambuc 574*f4a2713aSLionel Sambuc void elf_function_args() EXCLUSIVE_LOCK_FUNCTION(mu1, mu2); 575*f4a2713aSLionel Sambuc 576*f4a2713aSLionel Sambuc int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); 577*f4a2713aSLionel Sambuc 578*f4a2713aSLionel Sambuc int elf_testfn(int y) { 579*f4a2713aSLionel Sambuc int x EXCLUSIVE_LOCK_FUNCTION() = y; // \ 580*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} 581*f4a2713aSLionel Sambuc return x; 582*f4a2713aSLionel Sambuc }; 583*f4a2713aSLionel Sambuc 584*f4a2713aSLionel Sambuc int elf_test_var EXCLUSIVE_LOCK_FUNCTION(); // \ 585*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} 586*f4a2713aSLionel Sambuc 587*f4a2713aSLionel Sambuc class ElfFoo { 588*f4a2713aSLionel Sambuc private: 589*f4a2713aSLionel Sambuc int test_field EXCLUSIVE_LOCK_FUNCTION(); // \ 590*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} 591*f4a2713aSLionel Sambuc void test_method() EXCLUSIVE_LOCK_FUNCTION(); 592*f4a2713aSLionel Sambuc }; 593*f4a2713aSLionel Sambuc 594*f4a2713aSLionel Sambuc class EXCLUSIVE_LOCK_FUNCTION() ElfTestClass { // \ 595*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} 596*f4a2713aSLionel Sambuc }; 597*f4a2713aSLionel Sambuc 598*f4a2713aSLionel Sambuc void elf_fun_params(int lvar EXCLUSIVE_LOCK_FUNCTION()); // \ 599*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} 600*f4a2713aSLionel Sambuc 601*f4a2713aSLionel Sambuc // Check argument parsing. 602*f4a2713aSLionel Sambuc 603*f4a2713aSLionel Sambuc // legal attribute arguments 604*f4a2713aSLionel Sambuc int elf_function_1() EXCLUSIVE_LOCK_FUNCTION(muWrapper.mu); 605*f4a2713aSLionel Sambuc int elf_function_2() EXCLUSIVE_LOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); 606*f4a2713aSLionel Sambuc int elf_function_3() EXCLUSIVE_LOCK_FUNCTION(muWrapper.getMu()); 607*f4a2713aSLionel Sambuc int elf_function_4() EXCLUSIVE_LOCK_FUNCTION(*muWrapper.getMuPointer()); 608*f4a2713aSLionel Sambuc int elf_function_5() EXCLUSIVE_LOCK_FUNCTION(&mu1); 609*f4a2713aSLionel Sambuc int elf_function_6() EXCLUSIVE_LOCK_FUNCTION(muRef); 610*f4a2713aSLionel Sambuc int elf_function_7() EXCLUSIVE_LOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); 611*f4a2713aSLionel Sambuc int elf_function_8() EXCLUSIVE_LOCK_FUNCTION(muPointer); 612*f4a2713aSLionel Sambuc int elf_function_9(Mutex x) EXCLUSIVE_LOCK_FUNCTION(1); 613*f4a2713aSLionel Sambuc int elf_function_9(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(1,2); 614*f4a2713aSLionel Sambuc 615*f4a2713aSLionel Sambuc 616*f4a2713aSLionel Sambuc // illegal attribute arguments 617*f4a2713aSLionel Sambuc int elf_function_bad_2() EXCLUSIVE_LOCK_FUNCTION("mu"); // \ 618*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'exclusive_lock_function' attribute because its argument is invalid}} 619*f4a2713aSLionel Sambuc int elf_function_bad_3() EXCLUSIVE_LOCK_FUNCTION(muDoublePointer); // \ 620*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} 621*f4a2713aSLionel Sambuc int elf_function_bad_4() EXCLUSIVE_LOCK_FUNCTION(umu); // \ 622*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} 623*f4a2713aSLionel Sambuc 624*f4a2713aSLionel Sambuc int elf_function_bad_1() EXCLUSIVE_LOCK_FUNCTION(1); // \ 625*f4a2713aSLionel Sambuc // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} 626*f4a2713aSLionel Sambuc int elf_function_bad_5(Mutex x) EXCLUSIVE_LOCK_FUNCTION(0); // \ 627*f4a2713aSLionel Sambuc // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} 628*f4a2713aSLionel Sambuc int elf_function_bad_6(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(0); // \ 629*f4a2713aSLionel Sambuc // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} 630*f4a2713aSLionel Sambuc int elf_function_bad_7() EXCLUSIVE_LOCK_FUNCTION(0); // \ 631*f4a2713aSLionel Sambuc // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} 632*f4a2713aSLionel Sambuc 633*f4a2713aSLionel Sambuc 634*f4a2713aSLionel Sambuc //-----------------------------------------// 635*f4a2713aSLionel Sambuc // Shared Lock Function (slf) 636*f4a2713aSLionel Sambuc //-----------------------------------------// 637*f4a2713aSLionel Sambuc 638*f4a2713aSLionel Sambuc #if !__has_attribute(shared_lock_function) 639*f4a2713aSLionel Sambuc #error "Should support shared_lock_function attribute" 640*f4a2713aSLionel Sambuc #endif 641*f4a2713aSLionel Sambuc 642*f4a2713aSLionel Sambuc // takes zero or more arguments, all locks (vars/fields) 643*f4a2713aSLionel Sambuc 644*f4a2713aSLionel Sambuc void slf_function() SHARED_LOCK_FUNCTION(); 645*f4a2713aSLionel Sambuc 646*f4a2713aSLionel Sambuc void slf_function_args() SHARED_LOCK_FUNCTION(mu1, mu2); 647*f4a2713aSLionel Sambuc 648*f4a2713aSLionel Sambuc int slf_testfn(int y) SHARED_LOCK_FUNCTION(); 649*f4a2713aSLionel Sambuc 650*f4a2713aSLionel Sambuc int slf_testfn(int y) { 651*f4a2713aSLionel Sambuc int x SHARED_LOCK_FUNCTION() = y; // \ 652*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} 653*f4a2713aSLionel Sambuc return x; 654*f4a2713aSLionel Sambuc }; 655*f4a2713aSLionel Sambuc 656*f4a2713aSLionel Sambuc int slf_test_var SHARED_LOCK_FUNCTION(); // \ 657*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} 658*f4a2713aSLionel Sambuc 659*f4a2713aSLionel Sambuc void slf_fun_params(int lvar SHARED_LOCK_FUNCTION()); // \ 660*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} 661*f4a2713aSLionel Sambuc 662*f4a2713aSLionel Sambuc class SlfFoo { 663*f4a2713aSLionel Sambuc private: 664*f4a2713aSLionel Sambuc int test_field SHARED_LOCK_FUNCTION(); // \ 665*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} 666*f4a2713aSLionel Sambuc void test_method() SHARED_LOCK_FUNCTION(); 667*f4a2713aSLionel Sambuc }; 668*f4a2713aSLionel Sambuc 669*f4a2713aSLionel Sambuc class SHARED_LOCK_FUNCTION() SlfTestClass { // \ 670*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} 671*f4a2713aSLionel Sambuc }; 672*f4a2713aSLionel Sambuc 673*f4a2713aSLionel Sambuc // Check argument parsing. 674*f4a2713aSLionel Sambuc 675*f4a2713aSLionel Sambuc // legal attribute arguments 676*f4a2713aSLionel Sambuc int slf_function_1() SHARED_LOCK_FUNCTION(muWrapper.mu); 677*f4a2713aSLionel Sambuc int slf_function_2() SHARED_LOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); 678*f4a2713aSLionel Sambuc int slf_function_3() SHARED_LOCK_FUNCTION(muWrapper.getMu()); 679*f4a2713aSLionel Sambuc int slf_function_4() SHARED_LOCK_FUNCTION(*muWrapper.getMuPointer()); 680*f4a2713aSLionel Sambuc int slf_function_5() SHARED_LOCK_FUNCTION(&mu1); 681*f4a2713aSLionel Sambuc int slf_function_6() SHARED_LOCK_FUNCTION(muRef); 682*f4a2713aSLionel Sambuc int slf_function_7() SHARED_LOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); 683*f4a2713aSLionel Sambuc int slf_function_8() SHARED_LOCK_FUNCTION(muPointer); 684*f4a2713aSLionel Sambuc int slf_function_9(Mutex x) SHARED_LOCK_FUNCTION(1); 685*f4a2713aSLionel Sambuc int slf_function_9(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(1,2); 686*f4a2713aSLionel Sambuc 687*f4a2713aSLionel Sambuc 688*f4a2713aSLionel Sambuc // illegal attribute arguments 689*f4a2713aSLionel Sambuc int slf_function_bad_2() SHARED_LOCK_FUNCTION("mu"); // \ 690*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'shared_lock_function' attribute because its argument is invalid}} 691*f4a2713aSLionel Sambuc int slf_function_bad_3() SHARED_LOCK_FUNCTION(muDoublePointer); // \ 692*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} 693*f4a2713aSLionel Sambuc int slf_function_bad_4() SHARED_LOCK_FUNCTION(umu); // \ 694*f4a2713aSLionel Sambuc // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} 695*f4a2713aSLionel Sambuc 696*f4a2713aSLionel Sambuc int slf_function_bad_1() SHARED_LOCK_FUNCTION(1); // \ 697*f4a2713aSLionel Sambuc // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} 698*f4a2713aSLionel Sambuc int slf_function_bad_5(Mutex x) SHARED_LOCK_FUNCTION(0); // \ 699*f4a2713aSLionel Sambuc // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} 700*f4a2713aSLionel Sambuc int slf_function_bad_6(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(0); // \ 701*f4a2713aSLionel Sambuc // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} 702*f4a2713aSLionel Sambuc int slf_function_bad_7() SHARED_LOCK_FUNCTION(0); // \ 703*f4a2713aSLionel Sambuc // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} 704*f4a2713aSLionel Sambuc 705*f4a2713aSLionel Sambuc 706*f4a2713aSLionel Sambuc //-----------------------------------------// 707*f4a2713aSLionel Sambuc // Exclusive TryLock Function (etf) 708*f4a2713aSLionel Sambuc //-----------------------------------------// 709*f4a2713aSLionel Sambuc 710*f4a2713aSLionel Sambuc #if !__has_attribute(exclusive_trylock_function) 711*f4a2713aSLionel Sambuc #error "Should support exclusive_trylock_function attribute" 712*f4a2713aSLionel Sambuc #endif 713*f4a2713aSLionel Sambuc 714*f4a2713aSLionel Sambuc // takes a mandatory boolean or integer argument specifying the retval 715*f4a2713aSLionel Sambuc // plus an optional list of locks (vars/fields) 716*f4a2713aSLionel Sambuc 717*f4a2713aSLionel Sambuc void etf_function() __attribute__((exclusive_trylock_function)); // \ 718*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 719*f4a2713aSLionel Sambuc 720*f4a2713aSLionel Sambuc void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2); 721*f4a2713aSLionel Sambuc 722*f4a2713aSLionel Sambuc void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); 723*f4a2713aSLionel Sambuc 724*f4a2713aSLionel Sambuc int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); 725*f4a2713aSLionel Sambuc 726*f4a2713aSLionel Sambuc int etf_testfn(int y) { 727*f4a2713aSLionel Sambuc int x EXCLUSIVE_TRYLOCK_FUNCTION(1) = y; // \ 728*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} 729*f4a2713aSLionel Sambuc return x; 730*f4a2713aSLionel Sambuc }; 731*f4a2713aSLionel Sambuc 732*f4a2713aSLionel Sambuc int etf_test_var EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ 733*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} 734*f4a2713aSLionel Sambuc 735*f4a2713aSLionel Sambuc class EtfFoo { 736*f4a2713aSLionel Sambuc private: 737*f4a2713aSLionel Sambuc int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ 738*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} 739*f4a2713aSLionel Sambuc void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); 740*f4a2713aSLionel Sambuc }; 741*f4a2713aSLionel Sambuc 742*f4a2713aSLionel Sambuc class EXCLUSIVE_TRYLOCK_FUNCTION(1) EtfTestClass { // \ 743*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} 744*f4a2713aSLionel Sambuc }; 745*f4a2713aSLionel Sambuc 746*f4a2713aSLionel Sambuc void etf_fun_params(int lvar EXCLUSIVE_TRYLOCK_FUNCTION(1)); // \ 747*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} 748*f4a2713aSLionel Sambuc 749*f4a2713aSLionel Sambuc // Check argument parsing. 750*f4a2713aSLionel Sambuc 751*f4a2713aSLionel Sambuc // legal attribute arguments 752*f4a2713aSLionel Sambuc int etf_function_1() EXCLUSIVE_TRYLOCK_FUNCTION(1, muWrapper.mu); 753*f4a2713aSLionel Sambuc int etf_function_2() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.muWrapper->mu); 754*f4a2713aSLionel Sambuc int etf_function_3() EXCLUSIVE_TRYLOCK_FUNCTION(1, muWrapper.getMu()); 755*f4a2713aSLionel Sambuc int etf_function_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, *muWrapper.getMuPointer()); 756*f4a2713aSLionel Sambuc int etf_function_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, &mu1); 757*f4a2713aSLionel Sambuc int etf_function_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, muRef); 758*f4a2713aSLionel Sambuc int etf_function_7() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); 759*f4a2713aSLionel Sambuc int etf_functetfn_8() EXCLUSIVE_TRYLOCK_FUNCTION(1, muPointer); 760*f4a2713aSLionel Sambuc int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); 761*f4a2713aSLionel Sambuc 762*f4a2713aSLionel Sambuc 763*f4a2713aSLionel Sambuc // illegal attribute arguments 764*f4a2713aSLionel Sambuc int etf_function_bad_1() EXCLUSIVE_TRYLOCK_FUNCTION(mu1); // \ 765*f4a2713aSLionel Sambuc // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} 766*f4a2713aSLionel Sambuc int etf_function_bad_2() EXCLUSIVE_TRYLOCK_FUNCTION("mu"); // \ 767*f4a2713aSLionel Sambuc // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} 768*f4a2713aSLionel Sambuc int etf_function_bad_3() EXCLUSIVE_TRYLOCK_FUNCTION(muDoublePointer); // \ 769*f4a2713aSLionel Sambuc // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} 770*f4a2713aSLionel Sambuc 771*f4a2713aSLionel Sambuc int etf_function_bad_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, "mu"); // \ 772*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'exclusive_trylock_function' attribute because its argument is invalid}} 773*f4a2713aSLionel Sambuc int etf_function_bad_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoublePointer); // \ 774*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} 775*f4a2713aSLionel Sambuc int etf_function_bad_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, umu); // \ 776*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} 777*f4a2713aSLionel Sambuc 778*f4a2713aSLionel Sambuc 779*f4a2713aSLionel Sambuc //-----------------------------------------// 780*f4a2713aSLionel Sambuc // Shared TryLock Function (stf) 781*f4a2713aSLionel Sambuc //-----------------------------------------// 782*f4a2713aSLionel Sambuc 783*f4a2713aSLionel Sambuc #if !__has_attribute(shared_trylock_function) 784*f4a2713aSLionel Sambuc #error "Should support shared_trylock_function attribute" 785*f4a2713aSLionel Sambuc #endif 786*f4a2713aSLionel Sambuc 787*f4a2713aSLionel Sambuc // takes a mandatory boolean or integer argument specifying the retval 788*f4a2713aSLionel Sambuc // plus an optional list of locks (vars/fields) 789*f4a2713aSLionel Sambuc 790*f4a2713aSLionel Sambuc void stf_function() __attribute__((shared_trylock_function)); // \ 791*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 792*f4a2713aSLionel Sambuc 793*f4a2713aSLionel Sambuc void stf_function_args() SHARED_TRYLOCK_FUNCTION(1, mu2); 794*f4a2713aSLionel Sambuc 795*f4a2713aSLionel Sambuc void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); 796*f4a2713aSLionel Sambuc 797*f4a2713aSLionel Sambuc int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); 798*f4a2713aSLionel Sambuc 799*f4a2713aSLionel Sambuc int stf_testfn(int y) { 800*f4a2713aSLionel Sambuc int x SHARED_TRYLOCK_FUNCTION(1) = y; // \ 801*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} 802*f4a2713aSLionel Sambuc return x; 803*f4a2713aSLionel Sambuc }; 804*f4a2713aSLionel Sambuc 805*f4a2713aSLionel Sambuc int stf_test_var SHARED_TRYLOCK_FUNCTION(1); // \ 806*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} 807*f4a2713aSLionel Sambuc 808*f4a2713aSLionel Sambuc void stf_fun_params(int lvar SHARED_TRYLOCK_FUNCTION(1)); // \ 809*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} 810*f4a2713aSLionel Sambuc 811*f4a2713aSLionel Sambuc 812*f4a2713aSLionel Sambuc class StfFoo { 813*f4a2713aSLionel Sambuc private: 814*f4a2713aSLionel Sambuc int test_field SHARED_TRYLOCK_FUNCTION(1); // \ 815*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} 816*f4a2713aSLionel Sambuc void test_method() SHARED_TRYLOCK_FUNCTION(1); 817*f4a2713aSLionel Sambuc }; 818*f4a2713aSLionel Sambuc 819*f4a2713aSLionel Sambuc class SHARED_TRYLOCK_FUNCTION(1) StfTestClass { // \ 820*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} 821*f4a2713aSLionel Sambuc }; 822*f4a2713aSLionel Sambuc 823*f4a2713aSLionel Sambuc // Check argument parsing. 824*f4a2713aSLionel Sambuc 825*f4a2713aSLionel Sambuc // legal attribute arguments 826*f4a2713aSLionel Sambuc int stf_function_1() SHARED_TRYLOCK_FUNCTION(1, muWrapper.mu); 827*f4a2713aSLionel Sambuc int stf_function_2() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.muWrapper->mu); 828*f4a2713aSLionel Sambuc int stf_function_3() SHARED_TRYLOCK_FUNCTION(1, muWrapper.getMu()); 829*f4a2713aSLionel Sambuc int stf_function_4() SHARED_TRYLOCK_FUNCTION(1, *muWrapper.getMuPointer()); 830*f4a2713aSLionel Sambuc int stf_function_5() SHARED_TRYLOCK_FUNCTION(1, &mu1); 831*f4a2713aSLionel Sambuc int stf_function_6() SHARED_TRYLOCK_FUNCTION(1, muRef); 832*f4a2713aSLionel Sambuc int stf_function_7() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); 833*f4a2713aSLionel Sambuc int stf_function_8() SHARED_TRYLOCK_FUNCTION(1, muPointer); 834*f4a2713aSLionel Sambuc int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); 835*f4a2713aSLionel Sambuc 836*f4a2713aSLionel Sambuc 837*f4a2713aSLionel Sambuc // illegal attribute arguments 838*f4a2713aSLionel Sambuc int stf_function_bad_1() SHARED_TRYLOCK_FUNCTION(mu1); // \ 839*f4a2713aSLionel Sambuc // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} 840*f4a2713aSLionel Sambuc int stf_function_bad_2() SHARED_TRYLOCK_FUNCTION("mu"); // \ 841*f4a2713aSLionel Sambuc // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} 842*f4a2713aSLionel Sambuc int stf_function_bad_3() SHARED_TRYLOCK_FUNCTION(muDoublePointer); // \ 843*f4a2713aSLionel Sambuc // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} 844*f4a2713aSLionel Sambuc 845*f4a2713aSLionel Sambuc int stf_function_bad_4() SHARED_TRYLOCK_FUNCTION(1, "mu"); // \ 846*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'shared_trylock_function' attribute because its argument is invalid}} 847*f4a2713aSLionel Sambuc int stf_function_bad_5() SHARED_TRYLOCK_FUNCTION(1, muDoublePointer); // \ 848*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} 849*f4a2713aSLionel Sambuc int stf_function_bad_6() SHARED_TRYLOCK_FUNCTION(1, umu); // \ 850*f4a2713aSLionel Sambuc // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} 851*f4a2713aSLionel Sambuc 852*f4a2713aSLionel Sambuc 853*f4a2713aSLionel Sambuc //-----------------------------------------// 854*f4a2713aSLionel Sambuc // Unlock Function (uf) 855*f4a2713aSLionel Sambuc //-----------------------------------------// 856*f4a2713aSLionel Sambuc 857*f4a2713aSLionel Sambuc #if !__has_attribute(unlock_function) 858*f4a2713aSLionel Sambuc #error "Should support unlock_function attribute" 859*f4a2713aSLionel Sambuc #endif 860*f4a2713aSLionel Sambuc 861*f4a2713aSLionel Sambuc // takes zero or more arguments, all locks (vars/fields) 862*f4a2713aSLionel Sambuc 863*f4a2713aSLionel Sambuc void uf_function() UNLOCK_FUNCTION(); 864*f4a2713aSLionel Sambuc 865*f4a2713aSLionel Sambuc void uf_function_args() UNLOCK_FUNCTION(mu1, mu2); 866*f4a2713aSLionel Sambuc 867*f4a2713aSLionel Sambuc int uf_testfn(int y) UNLOCK_FUNCTION(); 868*f4a2713aSLionel Sambuc 869*f4a2713aSLionel Sambuc int uf_testfn(int y) { 870*f4a2713aSLionel Sambuc int x UNLOCK_FUNCTION() = y; // \ 871*f4a2713aSLionel Sambuc // expected-warning {{'unlock_function' attribute only applies to functions and methods}} 872*f4a2713aSLionel Sambuc return x; 873*f4a2713aSLionel Sambuc }; 874*f4a2713aSLionel Sambuc 875*f4a2713aSLionel Sambuc int uf_test_var UNLOCK_FUNCTION(); // \ 876*f4a2713aSLionel Sambuc // expected-warning {{'unlock_function' attribute only applies to functions and methods}} 877*f4a2713aSLionel Sambuc 878*f4a2713aSLionel Sambuc class UfFoo { 879*f4a2713aSLionel Sambuc private: 880*f4a2713aSLionel Sambuc int test_field UNLOCK_FUNCTION(); // \ 881*f4a2713aSLionel Sambuc // expected-warning {{'unlock_function' attribute only applies to functions and methods}} 882*f4a2713aSLionel Sambuc void test_method() UNLOCK_FUNCTION(); 883*f4a2713aSLionel Sambuc }; 884*f4a2713aSLionel Sambuc 885*f4a2713aSLionel Sambuc class NO_THREAD_SAFETY_ANALYSIS UfTestClass { // \ 886*f4a2713aSLionel Sambuc // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} 887*f4a2713aSLionel Sambuc }; 888*f4a2713aSLionel Sambuc 889*f4a2713aSLionel Sambuc void uf_fun_params(int lvar UNLOCK_FUNCTION()); // \ 890*f4a2713aSLionel Sambuc // expected-warning {{'unlock_function' attribute only applies to functions and methods}} 891*f4a2713aSLionel Sambuc 892*f4a2713aSLionel Sambuc // Check argument parsing. 893*f4a2713aSLionel Sambuc 894*f4a2713aSLionel Sambuc // legal attribute arguments 895*f4a2713aSLionel Sambuc int uf_function_1() UNLOCK_FUNCTION(muWrapper.mu); 896*f4a2713aSLionel Sambuc int uf_function_2() UNLOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); 897*f4a2713aSLionel Sambuc int uf_function_3() UNLOCK_FUNCTION(muWrapper.getMu()); 898*f4a2713aSLionel Sambuc int uf_function_4() UNLOCK_FUNCTION(*muWrapper.getMuPointer()); 899*f4a2713aSLionel Sambuc int uf_function_5() UNLOCK_FUNCTION(&mu1); 900*f4a2713aSLionel Sambuc int uf_function_6() UNLOCK_FUNCTION(muRef); 901*f4a2713aSLionel Sambuc int uf_function_7() UNLOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); 902*f4a2713aSLionel Sambuc int uf_function_8() UNLOCK_FUNCTION(muPointer); 903*f4a2713aSLionel Sambuc int uf_function_9(Mutex x) UNLOCK_FUNCTION(1); 904*f4a2713aSLionel Sambuc int uf_function_9(Mutex x, Mutex y) UNLOCK_FUNCTION(1,2); 905*f4a2713aSLionel Sambuc 906*f4a2713aSLionel Sambuc 907*f4a2713aSLionel Sambuc // illegal attribute arguments 908*f4a2713aSLionel Sambuc int uf_function_bad_2() UNLOCK_FUNCTION("mu"); // \ 909*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'unlock_function' attribute because its argument is invalid}} 910*f4a2713aSLionel Sambuc int uf_function_bad_3() UNLOCK_FUNCTION(muDoublePointer); // \ 911*f4a2713aSLionel Sambuc // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} 912*f4a2713aSLionel Sambuc int uf_function_bad_4() UNLOCK_FUNCTION(umu); // \ 913*f4a2713aSLionel Sambuc // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} 914*f4a2713aSLionel Sambuc 915*f4a2713aSLionel Sambuc int uf_function_bad_1() UNLOCK_FUNCTION(1); // \ 916*f4a2713aSLionel Sambuc // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} 917*f4a2713aSLionel Sambuc int uf_function_bad_5(Mutex x) UNLOCK_FUNCTION(0); // \ 918*f4a2713aSLionel Sambuc // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} 919*f4a2713aSLionel Sambuc int uf_function_bad_6(Mutex x, Mutex y) UNLOCK_FUNCTION(0); // \ 920*f4a2713aSLionel Sambuc // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} 921*f4a2713aSLionel Sambuc int uf_function_bad_7() UNLOCK_FUNCTION(0); // \ 922*f4a2713aSLionel Sambuc // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} 923*f4a2713aSLionel Sambuc 924*f4a2713aSLionel Sambuc 925*f4a2713aSLionel Sambuc //-----------------------------------------// 926*f4a2713aSLionel Sambuc // Lock Returned (lr) 927*f4a2713aSLionel Sambuc //-----------------------------------------// 928*f4a2713aSLionel Sambuc 929*f4a2713aSLionel Sambuc #if !__has_attribute(lock_returned) 930*f4a2713aSLionel Sambuc #error "Should support lock_returned attribute" 931*f4a2713aSLionel Sambuc #endif 932*f4a2713aSLionel Sambuc 933*f4a2713aSLionel Sambuc // Takes exactly one argument, a var/field 934*f4a2713aSLionel Sambuc 935*f4a2713aSLionel Sambuc void lr_function() __attribute__((lock_returned)); // \ 936*f4a2713aSLionel Sambuc // expected-error {{'lock_returned' attribute takes one argument}} 937*f4a2713aSLionel Sambuc 938*f4a2713aSLionel Sambuc void lr_function_arg() LOCK_RETURNED(mu1); 939*f4a2713aSLionel Sambuc 940*f4a2713aSLionel Sambuc void lr_function_args() __attribute__((lock_returned(mu1, mu2))); // \ 941*f4a2713aSLionel Sambuc // expected-error {{'lock_returned' attribute takes one argument}} 942*f4a2713aSLionel Sambuc 943*f4a2713aSLionel Sambuc int lr_testfn(int y) LOCK_RETURNED(mu1); 944*f4a2713aSLionel Sambuc 945*f4a2713aSLionel Sambuc int lr_testfn(int y) { 946*f4a2713aSLionel Sambuc int x LOCK_RETURNED(mu1) = y; // \ 947*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute only applies to functions and methods}} 948*f4a2713aSLionel Sambuc return x; 949*f4a2713aSLionel Sambuc }; 950*f4a2713aSLionel Sambuc 951*f4a2713aSLionel Sambuc int lr_test_var LOCK_RETURNED(mu1); // \ 952*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute only applies to functions and methods}} 953*f4a2713aSLionel Sambuc 954*f4a2713aSLionel Sambuc void lr_fun_params(int lvar LOCK_RETURNED(mu1)); // \ 955*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute only applies to functions and methods}} 956*f4a2713aSLionel Sambuc 957*f4a2713aSLionel Sambuc class LrFoo { 958*f4a2713aSLionel Sambuc private: 959*f4a2713aSLionel Sambuc int test_field LOCK_RETURNED(mu1); // \ 960*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute only applies to functions and methods}} 961*f4a2713aSLionel Sambuc void test_method() LOCK_RETURNED(mu1); 962*f4a2713aSLionel Sambuc }; 963*f4a2713aSLionel Sambuc 964*f4a2713aSLionel Sambuc class LOCK_RETURNED(mu1) LrTestClass { // \ 965*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute only applies to functions and methods}} 966*f4a2713aSLionel Sambuc }; 967*f4a2713aSLionel Sambuc 968*f4a2713aSLionel Sambuc // Check argument parsing. 969*f4a2713aSLionel Sambuc 970*f4a2713aSLionel Sambuc // legal attribute arguments 971*f4a2713aSLionel Sambuc int lr_function_1() LOCK_RETURNED(muWrapper.mu); 972*f4a2713aSLionel Sambuc int lr_function_2() LOCK_RETURNED(muDoubleWrapper.muWrapper->mu); 973*f4a2713aSLionel Sambuc int lr_function_3() LOCK_RETURNED(muWrapper.getMu()); 974*f4a2713aSLionel Sambuc int lr_function_4() LOCK_RETURNED(*muWrapper.getMuPointer()); 975*f4a2713aSLionel Sambuc int lr_function_5() LOCK_RETURNED(&mu1); 976*f4a2713aSLionel Sambuc int lr_function_6() LOCK_RETURNED(muRef); 977*f4a2713aSLionel Sambuc int lr_function_7() LOCK_RETURNED(muDoubleWrapper.getWrapper()->getMu()); 978*f4a2713aSLionel Sambuc int lr_function_8() LOCK_RETURNED(muPointer); 979*f4a2713aSLionel Sambuc 980*f4a2713aSLionel Sambuc 981*f4a2713aSLionel Sambuc // illegal attribute arguments 982*f4a2713aSLionel Sambuc int lr_function_bad_1() LOCK_RETURNED(1); // \ 983*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} 984*f4a2713aSLionel Sambuc int lr_function_bad_2() LOCK_RETURNED("mu"); // \ 985*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'lock_returned' attribute because its argument is invalid}} 986*f4a2713aSLionel Sambuc int lr_function_bad_3() LOCK_RETURNED(muDoublePointer); // \ 987*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} 988*f4a2713aSLionel Sambuc int lr_function_bad_4() LOCK_RETURNED(umu); // \ 989*f4a2713aSLionel Sambuc // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}} 990*f4a2713aSLionel Sambuc 991*f4a2713aSLionel Sambuc 992*f4a2713aSLionel Sambuc 993*f4a2713aSLionel Sambuc //-----------------------------------------// 994*f4a2713aSLionel Sambuc // Locks Excluded (le) 995*f4a2713aSLionel Sambuc //-----------------------------------------// 996*f4a2713aSLionel Sambuc 997*f4a2713aSLionel Sambuc #if !__has_attribute(locks_excluded) 998*f4a2713aSLionel Sambuc #error "Should support locks_excluded attribute" 999*f4a2713aSLionel Sambuc #endif 1000*f4a2713aSLionel Sambuc 1001*f4a2713aSLionel Sambuc // takes one or more arguments, all locks (vars/fields) 1002*f4a2713aSLionel Sambuc 1003*f4a2713aSLionel Sambuc void le_function() __attribute__((locks_excluded)); // \ 1004*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 1005*f4a2713aSLionel Sambuc 1006*f4a2713aSLionel Sambuc void le_function_arg() LOCKS_EXCLUDED(mu1); 1007*f4a2713aSLionel Sambuc 1008*f4a2713aSLionel Sambuc void le_function_args() LOCKS_EXCLUDED(mu1, mu2); 1009*f4a2713aSLionel Sambuc 1010*f4a2713aSLionel Sambuc int le_testfn(int y) LOCKS_EXCLUDED(mu1); 1011*f4a2713aSLionel Sambuc 1012*f4a2713aSLionel Sambuc int le_testfn(int y) { 1013*f4a2713aSLionel Sambuc int x LOCKS_EXCLUDED(mu1) = y; // \ 1014*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} 1015*f4a2713aSLionel Sambuc return x; 1016*f4a2713aSLionel Sambuc }; 1017*f4a2713aSLionel Sambuc 1018*f4a2713aSLionel Sambuc int le_test_var LOCKS_EXCLUDED(mu1); // \ 1019*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} 1020*f4a2713aSLionel Sambuc 1021*f4a2713aSLionel Sambuc void le_fun_params(int lvar LOCKS_EXCLUDED(mu1)); // \ 1022*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} 1023*f4a2713aSLionel Sambuc 1024*f4a2713aSLionel Sambuc class LeFoo { 1025*f4a2713aSLionel Sambuc private: 1026*f4a2713aSLionel Sambuc int test_field LOCKS_EXCLUDED(mu1); // \ 1027*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} 1028*f4a2713aSLionel Sambuc void test_method() LOCKS_EXCLUDED(mu1); 1029*f4a2713aSLionel Sambuc }; 1030*f4a2713aSLionel Sambuc 1031*f4a2713aSLionel Sambuc class LOCKS_EXCLUDED(mu1) LeTestClass { // \ 1032*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} 1033*f4a2713aSLionel Sambuc }; 1034*f4a2713aSLionel Sambuc 1035*f4a2713aSLionel Sambuc // Check argument parsing. 1036*f4a2713aSLionel Sambuc 1037*f4a2713aSLionel Sambuc // legal attribute arguments 1038*f4a2713aSLionel Sambuc int le_function_1() LOCKS_EXCLUDED(muWrapper.mu); 1039*f4a2713aSLionel Sambuc int le_function_2() LOCKS_EXCLUDED(muDoubleWrapper.muWrapper->mu); 1040*f4a2713aSLionel Sambuc int le_function_3() LOCKS_EXCLUDED(muWrapper.getMu()); 1041*f4a2713aSLionel Sambuc int le_function_4() LOCKS_EXCLUDED(*muWrapper.getMuPointer()); 1042*f4a2713aSLionel Sambuc int le_function_5() LOCKS_EXCLUDED(&mu1); 1043*f4a2713aSLionel Sambuc int le_function_6() LOCKS_EXCLUDED(muRef); 1044*f4a2713aSLionel Sambuc int le_function_7() LOCKS_EXCLUDED(muDoubleWrapper.getWrapper()->getMu()); 1045*f4a2713aSLionel Sambuc int le_function_8() LOCKS_EXCLUDED(muPointer); 1046*f4a2713aSLionel Sambuc 1047*f4a2713aSLionel Sambuc 1048*f4a2713aSLionel Sambuc // illegal attribute arguments 1049*f4a2713aSLionel Sambuc int le_function_bad_1() LOCKS_EXCLUDED(1); // \ 1050*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} 1051*f4a2713aSLionel Sambuc int le_function_bad_2() LOCKS_EXCLUDED("mu"); // \ 1052*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'locks_excluded' attribute because its argument is invalid}} 1053*f4a2713aSLionel Sambuc int le_function_bad_3() LOCKS_EXCLUDED(muDoublePointer); // \ 1054*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} 1055*f4a2713aSLionel Sambuc int le_function_bad_4() LOCKS_EXCLUDED(umu); // \ 1056*f4a2713aSLionel Sambuc // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}} 1057*f4a2713aSLionel Sambuc 1058*f4a2713aSLionel Sambuc 1059*f4a2713aSLionel Sambuc 1060*f4a2713aSLionel Sambuc //-----------------------------------------// 1061*f4a2713aSLionel Sambuc // Exclusive Locks Required (elr) 1062*f4a2713aSLionel Sambuc //-----------------------------------------// 1063*f4a2713aSLionel Sambuc 1064*f4a2713aSLionel Sambuc #if !__has_attribute(exclusive_locks_required) 1065*f4a2713aSLionel Sambuc #error "Should support exclusive_locks_required attribute" 1066*f4a2713aSLionel Sambuc #endif 1067*f4a2713aSLionel Sambuc 1068*f4a2713aSLionel Sambuc // takes one or more arguments, all locks (vars/fields) 1069*f4a2713aSLionel Sambuc 1070*f4a2713aSLionel Sambuc void elr_function() __attribute__((exclusive_locks_required)); // \ 1071*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 1072*f4a2713aSLionel Sambuc 1073*f4a2713aSLionel Sambuc void elr_function_arg() EXCLUSIVE_LOCKS_REQUIRED(mu1); 1074*f4a2713aSLionel Sambuc 1075*f4a2713aSLionel Sambuc void elr_function_args() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2); 1076*f4a2713aSLionel Sambuc 1077*f4a2713aSLionel Sambuc int elr_testfn(int y) EXCLUSIVE_LOCKS_REQUIRED(mu1); 1078*f4a2713aSLionel Sambuc 1079*f4a2713aSLionel Sambuc int elr_testfn(int y) { 1080*f4a2713aSLionel Sambuc int x EXCLUSIVE_LOCKS_REQUIRED(mu1) = y; // \ 1081*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} 1082*f4a2713aSLionel Sambuc return x; 1083*f4a2713aSLionel Sambuc }; 1084*f4a2713aSLionel Sambuc 1085*f4a2713aSLionel Sambuc int elr_test_var EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ 1086*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} 1087*f4a2713aSLionel Sambuc 1088*f4a2713aSLionel Sambuc void elr_fun_params(int lvar EXCLUSIVE_LOCKS_REQUIRED(mu1)); // \ 1089*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} 1090*f4a2713aSLionel Sambuc 1091*f4a2713aSLionel Sambuc class ElrFoo { 1092*f4a2713aSLionel Sambuc private: 1093*f4a2713aSLionel Sambuc int test_field EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ 1094*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} 1095*f4a2713aSLionel Sambuc void test_method() EXCLUSIVE_LOCKS_REQUIRED(mu1); 1096*f4a2713aSLionel Sambuc }; 1097*f4a2713aSLionel Sambuc 1098*f4a2713aSLionel Sambuc class EXCLUSIVE_LOCKS_REQUIRED(mu1) ElrTestClass { // \ 1099*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} 1100*f4a2713aSLionel Sambuc }; 1101*f4a2713aSLionel Sambuc 1102*f4a2713aSLionel Sambuc // Check argument parsing. 1103*f4a2713aSLionel Sambuc 1104*f4a2713aSLionel Sambuc // legal attribute arguments 1105*f4a2713aSLionel Sambuc int elr_function_1() EXCLUSIVE_LOCKS_REQUIRED(muWrapper.mu); 1106*f4a2713aSLionel Sambuc int elr_function_2() EXCLUSIVE_LOCKS_REQUIRED(muDoubleWrapper.muWrapper->mu); 1107*f4a2713aSLionel Sambuc int elr_function_3() EXCLUSIVE_LOCKS_REQUIRED(muWrapper.getMu()); 1108*f4a2713aSLionel Sambuc int elr_function_4() EXCLUSIVE_LOCKS_REQUIRED(*muWrapper.getMuPointer()); 1109*f4a2713aSLionel Sambuc int elr_function_5() EXCLUSIVE_LOCKS_REQUIRED(&mu1); 1110*f4a2713aSLionel Sambuc int elr_function_6() EXCLUSIVE_LOCKS_REQUIRED(muRef); 1111*f4a2713aSLionel Sambuc int elr_function_7() EXCLUSIVE_LOCKS_REQUIRED(muDoubleWrapper.getWrapper()->getMu()); 1112*f4a2713aSLionel Sambuc int elr_function_8() EXCLUSIVE_LOCKS_REQUIRED(muPointer); 1113*f4a2713aSLionel Sambuc 1114*f4a2713aSLionel Sambuc 1115*f4a2713aSLionel Sambuc // illegal attribute arguments 1116*f4a2713aSLionel Sambuc int elr_function_bad_1() EXCLUSIVE_LOCKS_REQUIRED(1); // \ 1117*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} 1118*f4a2713aSLionel Sambuc int elr_function_bad_2() EXCLUSIVE_LOCKS_REQUIRED("mu"); // \ 1119*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'exclusive_locks_required' attribute because its argument is invalid}} 1120*f4a2713aSLionel Sambuc int elr_function_bad_3() EXCLUSIVE_LOCKS_REQUIRED(muDoublePointer); // \ 1121*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} 1122*f4a2713aSLionel Sambuc int elr_function_bad_4() EXCLUSIVE_LOCKS_REQUIRED(umu); // \ 1123*f4a2713aSLionel Sambuc // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} 1124*f4a2713aSLionel Sambuc 1125*f4a2713aSLionel Sambuc 1126*f4a2713aSLionel Sambuc 1127*f4a2713aSLionel Sambuc 1128*f4a2713aSLionel Sambuc //-----------------------------------------// 1129*f4a2713aSLionel Sambuc // Shared Locks Required (slr) 1130*f4a2713aSLionel Sambuc //-----------------------------------------// 1131*f4a2713aSLionel Sambuc 1132*f4a2713aSLionel Sambuc #if !__has_attribute(shared_locks_required) 1133*f4a2713aSLionel Sambuc #error "Should support shared_locks_required attribute" 1134*f4a2713aSLionel Sambuc #endif 1135*f4a2713aSLionel Sambuc 1136*f4a2713aSLionel Sambuc // takes one or more arguments, all locks (vars/fields) 1137*f4a2713aSLionel Sambuc 1138*f4a2713aSLionel Sambuc void slr_function() __attribute__((shared_locks_required)); // \ 1139*f4a2713aSLionel Sambuc // expected-error {{attribute takes at least 1 argument}} 1140*f4a2713aSLionel Sambuc 1141*f4a2713aSLionel Sambuc void slr_function_arg() SHARED_LOCKS_REQUIRED(mu1); 1142*f4a2713aSLionel Sambuc 1143*f4a2713aSLionel Sambuc void slr_function_args() SHARED_LOCKS_REQUIRED(mu1, mu2); 1144*f4a2713aSLionel Sambuc 1145*f4a2713aSLionel Sambuc int slr_testfn(int y) SHARED_LOCKS_REQUIRED(mu1); 1146*f4a2713aSLionel Sambuc 1147*f4a2713aSLionel Sambuc int slr_testfn(int y) { 1148*f4a2713aSLionel Sambuc int x SHARED_LOCKS_REQUIRED(mu1) = y; // \ 1149*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} 1150*f4a2713aSLionel Sambuc return x; 1151*f4a2713aSLionel Sambuc }; 1152*f4a2713aSLionel Sambuc 1153*f4a2713aSLionel Sambuc int slr_test_var SHARED_LOCKS_REQUIRED(mu1); // \ 1154*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} 1155*f4a2713aSLionel Sambuc 1156*f4a2713aSLionel Sambuc void slr_fun_params(int lvar SHARED_LOCKS_REQUIRED(mu1)); // \ 1157*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} 1158*f4a2713aSLionel Sambuc 1159*f4a2713aSLionel Sambuc class SlrFoo { 1160*f4a2713aSLionel Sambuc private: 1161*f4a2713aSLionel Sambuc int test_field SHARED_LOCKS_REQUIRED(mu1); // \ 1162*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} 1163*f4a2713aSLionel Sambuc void test_method() SHARED_LOCKS_REQUIRED(mu1); 1164*f4a2713aSLionel Sambuc }; 1165*f4a2713aSLionel Sambuc 1166*f4a2713aSLionel Sambuc class SHARED_LOCKS_REQUIRED(mu1) SlrTestClass { // \ 1167*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} 1168*f4a2713aSLionel Sambuc }; 1169*f4a2713aSLionel Sambuc 1170*f4a2713aSLionel Sambuc // Check argument parsing. 1171*f4a2713aSLionel Sambuc 1172*f4a2713aSLionel Sambuc // legal attribute arguments 1173*f4a2713aSLionel Sambuc int slr_function_1() SHARED_LOCKS_REQUIRED(muWrapper.mu); 1174*f4a2713aSLionel Sambuc int slr_function_2() SHARED_LOCKS_REQUIRED(muDoubleWrapper.muWrapper->mu); 1175*f4a2713aSLionel Sambuc int slr_function_3() SHARED_LOCKS_REQUIRED(muWrapper.getMu()); 1176*f4a2713aSLionel Sambuc int slr_function_4() SHARED_LOCKS_REQUIRED(*muWrapper.getMuPointer()); 1177*f4a2713aSLionel Sambuc int slr_function_5() SHARED_LOCKS_REQUIRED(&mu1); 1178*f4a2713aSLionel Sambuc int slr_function_6() SHARED_LOCKS_REQUIRED(muRef); 1179*f4a2713aSLionel Sambuc int slr_function_7() SHARED_LOCKS_REQUIRED(muDoubleWrapper.getWrapper()->getMu()); 1180*f4a2713aSLionel Sambuc int slr_function_8() SHARED_LOCKS_REQUIRED(muPointer); 1181*f4a2713aSLionel Sambuc 1182*f4a2713aSLionel Sambuc 1183*f4a2713aSLionel Sambuc // illegal attribute arguments 1184*f4a2713aSLionel Sambuc int slr_function_bad_1() SHARED_LOCKS_REQUIRED(1); // \ 1185*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} 1186*f4a2713aSLionel Sambuc int slr_function_bad_2() SHARED_LOCKS_REQUIRED("mu"); // \ 1187*f4a2713aSLionel Sambuc // expected-warning {{ignoring 'shared_locks_required' attribute because its argument is invalid}} 1188*f4a2713aSLionel Sambuc int slr_function_bad_3() SHARED_LOCKS_REQUIRED(muDoublePointer); // \ 1189*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} 1190*f4a2713aSLionel Sambuc int slr_function_bad_4() SHARED_LOCKS_REQUIRED(umu); // \ 1191*f4a2713aSLionel Sambuc // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} 1192*f4a2713aSLionel Sambuc 1193*f4a2713aSLionel Sambuc 1194*f4a2713aSLionel Sambuc //-----------------------------------------// 1195*f4a2713aSLionel Sambuc // Regression tests for unusual cases. 1196*f4a2713aSLionel Sambuc //-----------------------------------------// 1197*f4a2713aSLionel Sambuc 1198*f4a2713aSLionel Sambuc int trivially_false_edges(bool b) { 1199*f4a2713aSLionel Sambuc // Create NULL (never taken) edges in CFG 1200*f4a2713aSLionel Sambuc if (false) return 1; 1201*f4a2713aSLionel Sambuc else return 2; 1202*f4a2713aSLionel Sambuc } 1203*f4a2713aSLionel Sambuc 1204*f4a2713aSLionel Sambuc // Possible Clang bug -- method pointer in template parameter 1205*f4a2713aSLionel Sambuc class UnFoo { 1206*f4a2713aSLionel Sambuc public: 1207*f4a2713aSLionel Sambuc void foo(); 1208*f4a2713aSLionel Sambuc }; 1209*f4a2713aSLionel Sambuc 1210*f4a2713aSLionel Sambuc template<void (UnFoo::*methptr)()> 1211*f4a2713aSLionel Sambuc class MCaller { 1212*f4a2713aSLionel Sambuc public: 1213*f4a2713aSLionel Sambuc static void call_method_ptr(UnFoo *f) { 1214*f4a2713aSLionel Sambuc // FIXME: Possible Clang bug: 1215*f4a2713aSLionel Sambuc // getCalleeDecl() returns NULL in the following case: 1216*f4a2713aSLionel Sambuc (f->*methptr)(); 1217*f4a2713aSLionel Sambuc } 1218*f4a2713aSLionel Sambuc }; 1219*f4a2713aSLionel Sambuc 1220*f4a2713aSLionel Sambuc void call_method_ptr_inst(UnFoo* f) { 1221*f4a2713aSLionel Sambuc MCaller<&UnFoo::foo>::call_method_ptr(f); 1222*f4a2713aSLionel Sambuc } 1223*f4a2713aSLionel Sambuc 1224*f4a2713aSLionel Sambuc int temp; 1225*f4a2713aSLionel Sambuc void empty_back_edge() { 1226*f4a2713aSLionel Sambuc // Create a back edge to a block with with no statements 1227*f4a2713aSLionel Sambuc for (;;) { 1228*f4a2713aSLionel Sambuc ++temp; 1229*f4a2713aSLionel Sambuc if (temp > 10) break; 1230*f4a2713aSLionel Sambuc } 1231*f4a2713aSLionel Sambuc } 1232*f4a2713aSLionel Sambuc 1233*f4a2713aSLionel Sambuc struct Foomger { 1234*f4a2713aSLionel Sambuc void operator++(); 1235*f4a2713aSLionel Sambuc }; 1236*f4a2713aSLionel Sambuc 1237*f4a2713aSLionel Sambuc struct Foomgoper { 1238*f4a2713aSLionel Sambuc Foomger f; 1239*f4a2713aSLionel Sambuc 1240*f4a2713aSLionel Sambuc bool done(); 1241*f4a2713aSLionel Sambuc void invalid_back_edge() { 1242*f4a2713aSLionel Sambuc do { 1243*f4a2713aSLionel Sambuc // FIXME: Possible Clang bug: 1244*f4a2713aSLionel Sambuc // The first statement in this basic block has no source location 1245*f4a2713aSLionel Sambuc ++f; 1246*f4a2713aSLionel Sambuc } while (!done()); 1247*f4a2713aSLionel Sambuc } 1248*f4a2713aSLionel Sambuc }; 1249*f4a2713aSLionel Sambuc 1250*f4a2713aSLionel Sambuc 1251*f4a2713aSLionel Sambuc //----------------------------------------------------- 1252*f4a2713aSLionel Sambuc // Parsing of member variables and function parameters 1253*f4a2713aSLionel Sambuc //------------------------------------------------------ 1254*f4a2713aSLionel Sambuc 1255*f4a2713aSLionel Sambuc Mutex gmu; 1256*f4a2713aSLionel Sambuc 1257*f4a2713aSLionel Sambuc class StaticMu { 1258*f4a2713aSLionel Sambuc static Mutex statmu; 1259*f4a2713aSLionel Sambuc }; 1260*f4a2713aSLionel Sambuc 1261*f4a2713aSLionel Sambuc class FooLate { 1262*f4a2713aSLionel Sambuc public: 1263*f4a2713aSLionel Sambuc void foo1() EXCLUSIVE_LOCKS_REQUIRED(gmu) { } 1264*f4a2713aSLionel Sambuc void foo2() EXCLUSIVE_LOCKS_REQUIRED(mu) { } 1265*f4a2713aSLionel Sambuc void foo3(Mutex *m) EXCLUSIVE_LOCKS_REQUIRED(m) { } 1266*f4a2713aSLionel Sambuc void foo3(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu) { } 1267*f4a2713aSLionel Sambuc void foo4(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu); 1268*f4a2713aSLionel Sambuc 1269*f4a2713aSLionel Sambuc static void foo5() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ 1270*f4a2713aSLionel Sambuc // expected-error {{invalid use of member 'mu' in static member function}} 1271*f4a2713aSLionel Sambuc 1272*f4a2713aSLionel Sambuc template <class T> 1273*f4a2713aSLionel Sambuc void foo6() EXCLUSIVE_LOCKS_REQUIRED(T::statmu) { } 1274*f4a2713aSLionel Sambuc 1275*f4a2713aSLionel Sambuc template <class T> 1276*f4a2713aSLionel Sambuc void foo7(T* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu) { } 1277*f4a2713aSLionel Sambuc 1278*f4a2713aSLionel Sambuc int a GUARDED_BY(gmu); 1279*f4a2713aSLionel Sambuc int b GUARDED_BY(mu); 1280*f4a2713aSLionel Sambuc int c GUARDED_BY(this->mu); 1281*f4a2713aSLionel Sambuc 1282*f4a2713aSLionel Sambuc Mutex mu; 1283*f4a2713aSLionel Sambuc }; 1284*f4a2713aSLionel Sambuc 1285*f4a2713aSLionel Sambuc //------------------------- 1286*f4a2713aSLionel Sambuc // Empty argument lists 1287*f4a2713aSLionel Sambuc //------------------------- 1288*f4a2713aSLionel Sambuc 1289*f4a2713aSLionel Sambuc class LOCKABLE EmptyArgListsTest { 1290*f4a2713aSLionel Sambuc void lock() EXCLUSIVE_LOCK_FUNCTION() { } 1291*f4a2713aSLionel Sambuc void unlock() UNLOCK_FUNCTION() { } 1292*f4a2713aSLionel Sambuc }; 1293*f4a2713aSLionel Sambuc 1294*f4a2713aSLionel Sambuc 1295*f4a2713aSLionel Sambuc namespace FunctionDefinitionParseTest { 1296*f4a2713aSLionel Sambuc // Test parsing of attributes on function definitions. 1297*f4a2713aSLionel Sambuc 1298*f4a2713aSLionel Sambuc class Foo { 1299*f4a2713aSLionel Sambuc public: 1300*f4a2713aSLionel Sambuc Mutex mu_; 1301*f4a2713aSLionel Sambuc void foo1(); 1302*f4a2713aSLionel Sambuc void foo2(Foo *f); 1303*f4a2713aSLionel Sambuc }; 1304*f4a2713aSLionel Sambuc 1305*f4a2713aSLionel Sambuc template <class T> 1306*f4a2713aSLionel Sambuc class Bar { 1307*f4a2713aSLionel Sambuc public: 1308*f4a2713aSLionel Sambuc Mutex mu_; 1309*f4a2713aSLionel Sambuc void bar(); 1310*f4a2713aSLionel Sambuc }; 1311*f4a2713aSLionel Sambuc 1312*f4a2713aSLionel Sambuc void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) { } 1313*f4a2713aSLionel Sambuc void Foo::foo2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { } 1314*f4a2713aSLionel Sambuc 1315*f4a2713aSLionel Sambuc template <class T> 1316*f4a2713aSLionel Sambuc void Bar<T>::bar() EXCLUSIVE_LOCKS_REQUIRED(mu_) { } 1317*f4a2713aSLionel Sambuc 1318*f4a2713aSLionel Sambuc void baz(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { } 1319*f4a2713aSLionel Sambuc 1320*f4a2713aSLionel Sambuc } // end namespace 1321*f4a2713aSLionel Sambuc 1322*f4a2713aSLionel Sambuc 1323*f4a2713aSLionel Sambuc namespace TestMultiDecl { 1324*f4a2713aSLionel Sambuc 1325*f4a2713aSLionel Sambuc class Foo { 1326*f4a2713aSLionel Sambuc public: 1327*f4a2713aSLionel Sambuc int GUARDED_BY(mu_) a; 1328*f4a2713aSLionel Sambuc int GUARDED_BY(mu_) b, c; 1329*f4a2713aSLionel Sambuc 1330*f4a2713aSLionel Sambuc private: 1331*f4a2713aSLionel Sambuc Mutex mu_; 1332*f4a2713aSLionel Sambuc }; 1333*f4a2713aSLionel Sambuc 1334*f4a2713aSLionel Sambuc } // end namespace TestMultiDecl 1335*f4a2713aSLionel Sambuc 1336*f4a2713aSLionel Sambuc 1337*f4a2713aSLionel Sambuc namespace NestedClassLateDecl { 1338*f4a2713aSLionel Sambuc 1339*f4a2713aSLionel Sambuc class Foo { 1340*f4a2713aSLionel Sambuc class Bar { 1341*f4a2713aSLionel Sambuc int a GUARDED_BY(mu); 1342*f4a2713aSLionel Sambuc int b GUARDED_BY(fooMuStatic); 1343*f4a2713aSLionel Sambuc 1344*f4a2713aSLionel Sambuc void bar() EXCLUSIVE_LOCKS_REQUIRED(mu) { a = 0; } 1345*f4a2713aSLionel Sambuc void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu) { b->a = 0; } 1346*f4a2713aSLionel Sambuc void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; } 1347*f4a2713aSLionel Sambuc 1348*f4a2713aSLionel Sambuc Mutex mu; 1349*f4a2713aSLionel Sambuc }; 1350*f4a2713aSLionel Sambuc 1351*f4a2713aSLionel Sambuc int a GUARDED_BY(fooMu); 1352*f4a2713aSLionel Sambuc Mutex fooMu; 1353*f4a2713aSLionel Sambuc static Mutex fooMuStatic; 1354*f4a2713aSLionel Sambuc }; 1355*f4a2713aSLionel Sambuc 1356*f4a2713aSLionel Sambuc } 1357*f4a2713aSLionel Sambuc 1358*f4a2713aSLionel Sambuc namespace PointerToMemberTest { 1359*f4a2713aSLionel Sambuc 1360*f4a2713aSLionel Sambuc // Empty string should be ignored. 1361*f4a2713aSLionel Sambuc int testEmptyAttribute GUARDED_BY(""); 1362*f4a2713aSLionel Sambuc void testEmptyAttributeFunction() EXCLUSIVE_LOCKS_REQUIRED(""); 1363*f4a2713aSLionel Sambuc 1364*f4a2713aSLionel Sambuc class Graph { 1365*f4a2713aSLionel Sambuc public: 1366*f4a2713aSLionel Sambuc Mutex mu_; 1367*f4a2713aSLionel Sambuc 1368*f4a2713aSLionel Sambuc static Mutex* get_static_mu() LOCK_RETURNED(&Graph::mu_); 1369*f4a2713aSLionel Sambuc }; 1370*f4a2713aSLionel Sambuc 1371*f4a2713aSLionel Sambuc class Node { 1372*f4a2713aSLionel Sambuc public: 1373*f4a2713aSLionel Sambuc void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_); 1374*f4a2713aSLionel Sambuc int a GUARDED_BY(&Graph::mu_); 1375*f4a2713aSLionel Sambuc }; 1376*f4a2713aSLionel Sambuc 1377*f4a2713aSLionel Sambuc } 1378*f4a2713aSLionel Sambuc 1379*f4a2713aSLionel Sambuc 1380*f4a2713aSLionel Sambuc namespace SmartPointerTest { 1381*f4a2713aSLionel Sambuc 1382*f4a2713aSLionel Sambuc template<class T> 1383*f4a2713aSLionel Sambuc class smart_ptr { 1384*f4a2713aSLionel Sambuc public: 1385*f4a2713aSLionel Sambuc T* operator->() { return ptr_; } 1386*f4a2713aSLionel Sambuc T& operator*() { return ptr_; } 1387*f4a2713aSLionel Sambuc 1388*f4a2713aSLionel Sambuc private: 1389*f4a2713aSLionel Sambuc T* ptr_; 1390*f4a2713aSLionel Sambuc }; 1391*f4a2713aSLionel Sambuc 1392*f4a2713aSLionel Sambuc 1393*f4a2713aSLionel Sambuc Mutex gmu; 1394*f4a2713aSLionel Sambuc smart_ptr<int> gdat PT_GUARDED_BY(gmu); 1395*f4a2713aSLionel Sambuc 1396*f4a2713aSLionel Sambuc 1397*f4a2713aSLionel Sambuc class MyClass { 1398*f4a2713aSLionel Sambuc public: 1399*f4a2713aSLionel Sambuc Mutex mu_; 1400*f4a2713aSLionel Sambuc smart_ptr<Mutex> smu_; 1401*f4a2713aSLionel Sambuc 1402*f4a2713aSLionel Sambuc 1403*f4a2713aSLionel Sambuc smart_ptr<int> a PT_GUARDED_BY(mu_); 1404*f4a2713aSLionel Sambuc int b GUARDED_BY(smu_); 1405*f4a2713aSLionel Sambuc }; 1406*f4a2713aSLionel Sambuc 1407*f4a2713aSLionel Sambuc } 1408*f4a2713aSLionel Sambuc 1409*f4a2713aSLionel Sambuc 1410*f4a2713aSLionel Sambuc namespace InheritanceTest { 1411*f4a2713aSLionel Sambuc 1412*f4a2713aSLionel Sambuc class LOCKABLE Base { 1413*f4a2713aSLionel Sambuc public: 1414*f4a2713aSLionel Sambuc void lock() EXCLUSIVE_LOCK_FUNCTION(); 1415*f4a2713aSLionel Sambuc void unlock() UNLOCK_FUNCTION(); 1416*f4a2713aSLionel Sambuc }; 1417*f4a2713aSLionel Sambuc 1418*f4a2713aSLionel Sambuc class Base2 { }; 1419*f4a2713aSLionel Sambuc 1420*f4a2713aSLionel Sambuc class Derived1 : public Base { }; 1421*f4a2713aSLionel Sambuc 1422*f4a2713aSLionel Sambuc class Derived2 : public Base2, public Derived1 { }; 1423*f4a2713aSLionel Sambuc 1424*f4a2713aSLionel Sambuc class Derived3 : public Base2 { }; 1425*f4a2713aSLionel Sambuc 1426*f4a2713aSLionel Sambuc class Foo { 1427*f4a2713aSLionel Sambuc Derived1 mu1_; 1428*f4a2713aSLionel Sambuc Derived2 mu2_; 1429*f4a2713aSLionel Sambuc Derived3 mu3_; 1430*f4a2713aSLionel Sambuc int a GUARDED_BY(mu1_); 1431*f4a2713aSLionel Sambuc int b GUARDED_BY(mu2_); 1432*f4a2713aSLionel Sambuc int c GUARDED_BY(mu3_); // \ 1433*f4a2713aSLionel Sambuc // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class InheritanceTest::Derived3'}} 1434*f4a2713aSLionel Sambuc 1435*f4a2713aSLionel Sambuc void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1_, mu2_) { 1436*f4a2713aSLionel Sambuc a = 0; 1437*f4a2713aSLionel Sambuc b = 0; 1438*f4a2713aSLionel Sambuc } 1439*f4a2713aSLionel Sambuc }; 1440*f4a2713aSLionel Sambuc 1441*f4a2713aSLionel Sambuc } 1442*f4a2713aSLionel Sambuc 1443*f4a2713aSLionel Sambuc 1444*f4a2713aSLionel Sambuc namespace InvalidDeclTest { 1445*f4a2713aSLionel Sambuc 1446*f4a2713aSLionel Sambuc class Foo { }; 1447*f4a2713aSLionel Sambuc namespace { 1448*f4a2713aSLionel Sambuc void Foo::bar(Mutex* mu) LOCKS_EXCLUDED(mu) { } // \ 1449*f4a2713aSLionel Sambuc // expected-error {{cannot define or redeclare 'bar' here because namespace '' does not enclose namespace 'Foo'}} \ 1450*f4a2713aSLionel Sambuc // expected-warning {{attribute locks_excluded ignored, because it is not attached to a declaration}} 1451*f4a2713aSLionel Sambuc } 1452*f4a2713aSLionel Sambuc 1453*f4a2713aSLionel Sambuc } // end namespace InvalidDeclTest 1454*f4a2713aSLionel Sambuc 1455*f4a2713aSLionel Sambuc 1456*f4a2713aSLionel Sambuc namespace StaticScopeTest { 1457*f4a2713aSLionel Sambuc 1458*f4a2713aSLionel Sambuc class FooStream; 1459*f4a2713aSLionel Sambuc 1460*f4a2713aSLionel Sambuc class Foo { 1461*f4a2713aSLionel Sambuc mutable Mutex mu; 1462*f4a2713aSLionel Sambuc int a GUARDED_BY(mu); 1463*f4a2713aSLionel Sambuc 1464*f4a2713aSLionel Sambuc static int si GUARDED_BY(mu); // \ 1465*f4a2713aSLionel Sambuc // expected-error {{invalid use of non-static data member 'mu'}} 1466*f4a2713aSLionel Sambuc 1467*f4a2713aSLionel Sambuc static void foo() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ 1468*f4a2713aSLionel Sambuc // expected-error {{invalid use of member 'mu' in static member function}} 1469*f4a2713aSLionel Sambuc 1470*f4a2713aSLionel Sambuc friend FooStream& operator<<(FooStream& s, const Foo& f) 1471*f4a2713aSLionel Sambuc EXCLUSIVE_LOCKS_REQUIRED(mu); // \ 1472*f4a2713aSLionel Sambuc // expected-error {{invalid use of non-static data member 'mu'}} 1473*f4a2713aSLionel Sambuc }; 1474*f4a2713aSLionel Sambuc 1475*f4a2713aSLionel Sambuc 1476*f4a2713aSLionel Sambuc } // end namespace StaticScopeTest 1477*f4a2713aSLionel Sambuc 1478*f4a2713aSLionel Sambuc 1479*f4a2713aSLionel Sambuc namespace FunctionAttributesInsideClass_ICE_Test { 1480*f4a2713aSLionel Sambuc 1481*f4a2713aSLionel Sambuc class Foo { 1482*f4a2713aSLionel Sambuc public: 1483*f4a2713aSLionel Sambuc /* Originally found when parsing foo() as an ordinary method after the 1484*f4a2713aSLionel Sambuc * the following: 1485*f4a2713aSLionel Sambuc 1486*f4a2713aSLionel Sambuc template <class T> 1487*f4a2713aSLionel Sambuc void syntaxErrorMethod(int i) { 1488*f4a2713aSLionel Sambuc if (i) { 1489*f4a2713aSLionel Sambuc foo( 1490*f4a2713aSLionel Sambuc } 1491*f4a2713aSLionel Sambuc } 1492*f4a2713aSLionel Sambuc */ 1493*f4a2713aSLionel Sambuc 1494*f4a2713aSLionel Sambuc void method() { 1495*f4a2713aSLionel Sambuc void foo() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ 1496*f4a2713aSLionel Sambuc // expected-error {{use of undeclared identifier 'mu'}} 1497*f4a2713aSLionel Sambuc } 1498*f4a2713aSLionel Sambuc }; 1499*f4a2713aSLionel Sambuc 1500*f4a2713aSLionel Sambuc } // end namespace FunctionAttributesInsideClass_ICE_Test 1501*f4a2713aSLionel Sambuc 1502