1f51a89d39
These were ignored by git accidentally. We want ALL OF THEM since they all came in the llvm/clang source distribution.
1346 lines
54 KiB
C++
1346 lines
54 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
|
|
|
|
#define LOCKABLE __attribute__ ((lockable))
|
|
#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
|
|
#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
|
|
#define GUARDED_VAR __attribute__ ((guarded_var))
|
|
#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
|
|
#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
|
|
#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
|
|
#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
|
|
#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
|
|
#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
|
|
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
|
|
#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
|
|
#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
|
|
#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
|
|
#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
|
|
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
|
|
__attribute__ ((exclusive_locks_required(__VA_ARGS__)))
|
|
#define SHARED_LOCKS_REQUIRED(...) \
|
|
__attribute__ ((shared_locks_required(__VA_ARGS__)))
|
|
#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
|
|
|
|
|
|
class __attribute__((lockable)) Mu {
|
|
public:
|
|
void Lock();
|
|
};
|
|
|
|
class UnlockableMu{
|
|
};
|
|
|
|
class MuWrapper {
|
|
public:
|
|
Mu mu;
|
|
Mu getMu() {
|
|
return mu;
|
|
}
|
|
Mu * getMuPointer() {
|
|
return μ
|
|
}
|
|
};
|
|
|
|
|
|
class MuDoubleWrapper {
|
|
public:
|
|
MuWrapper* muWrapper;
|
|
MuWrapper* getWrapper() {
|
|
return muWrapper;
|
|
}
|
|
};
|
|
|
|
Mu mu1;
|
|
UnlockableMu umu;
|
|
Mu mu2;
|
|
MuWrapper muWrapper;
|
|
MuDoubleWrapper muDoubleWrapper;
|
|
Mu* muPointer;
|
|
Mu ** muDoublePointer = & muPointer;
|
|
Mu& muRef = mu1;
|
|
|
|
//---------------------------------------//
|
|
// Scoping tests
|
|
//--------------------------------------//
|
|
|
|
class Foo {
|
|
Mu foomu;
|
|
void needLock() __attribute__((exclusive_lock_function(foomu)));
|
|
};
|
|
|
|
class Foo2 {
|
|
void needLock() __attribute__((exclusive_lock_function(foomu)));
|
|
Mu foomu;
|
|
};
|
|
|
|
class Bar {
|
|
Mu barmu;
|
|
Mu barmu2 __attribute__((acquired_after(barmu)));
|
|
};
|
|
|
|
|
|
//-----------------------------------------//
|
|
// No Thread Safety Analysis (noanal) //
|
|
//-----------------------------------------//
|
|
|
|
// FIXME: Right now we cannot parse attributes put on function definitions
|
|
// We would like to patch this at some point.
|
|
|
|
#if !__has_attribute(no_thread_safety_analysis)
|
|
#error "Should support no_thread_safety_analysis attribute"
|
|
#endif
|
|
|
|
void noanal_fun() __attribute__((no_thread_safety_analysis));
|
|
|
|
void noanal_fun_args() __attribute__((no_thread_safety_analysis(1))); // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
|
|
int noanal_testfn(int y) __attribute__((no_thread_safety_analysis));
|
|
|
|
int noanal_testfn(int y) {
|
|
int x __attribute__((no_thread_safety_analysis)) = y; // \
|
|
// expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int noanal_test_var __attribute__((no_thread_safety_analysis)); // \
|
|
// expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
|
|
|
|
class NoanalFoo {
|
|
private:
|
|
int test_field __attribute__((no_thread_safety_analysis)); // \
|
|
// expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((no_thread_safety_analysis));
|
|
};
|
|
|
|
class __attribute__((no_thread_safety_analysis)) NoanalTestClass { // \
|
|
// expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
void noanal_fun_params(int lvar __attribute__((no_thread_safety_analysis))); // \
|
|
// expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Guarded Var Attribute (gv)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(guarded_var)
|
|
#error "Should support guarded_var attribute"
|
|
#endif
|
|
|
|
int gv_var_noargs __attribute__((guarded_var));
|
|
|
|
int gv_var_args __attribute__((guarded_var(1))); // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
|
|
class GVFoo {
|
|
private:
|
|
int gv_field_noargs __attribute__((guarded_var));
|
|
int gv_field_args __attribute__((guarded_var(1))); // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
};
|
|
|
|
class __attribute__((guarded_var)) GV { // \
|
|
// expected-warning {{'guarded_var' attribute only applies to fields and global variables}}
|
|
};
|
|
|
|
void gv_function() __attribute__((guarded_var)); // \
|
|
// expected-warning {{'guarded_var' attribute only applies to fields and global variables}}
|
|
|
|
void gv_function_params(int gv_lvar __attribute__((guarded_var))); // \
|
|
// expected-warning {{'guarded_var' attribute only applies to fields and global variables}}
|
|
|
|
int gv_testfn(int y){
|
|
int x __attribute__((guarded_var)) = y; // \
|
|
// expected-warning {{'guarded_var' attribute only applies to fields and global variables}}
|
|
return x;
|
|
}
|
|
|
|
//-----------------------------------------//
|
|
// Pt Guarded Var Attribute (pgv)
|
|
//-----------------------------------------//
|
|
|
|
//FIXME: add support for boost::scoped_ptr<int> fancyptr and references
|
|
|
|
#if !__has_attribute(pt_guarded_var)
|
|
#error "Should support pt_guarded_var attribute"
|
|
#endif
|
|
|
|
int *pgv_pt_var_noargs __attribute__((pt_guarded_var));
|
|
|
|
int pgv_var_noargs __attribute__((pt_guarded_var)); // \
|
|
// expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
|
|
|
|
class PGVFoo {
|
|
private:
|
|
int *pt_field_noargs __attribute__((pt_guarded_var));
|
|
int field_noargs __attribute__((pt_guarded_var)); // \
|
|
// expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
|
|
int *gv_field_args __attribute__((pt_guarded_var(1))); // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
};
|
|
|
|
class __attribute__((pt_guarded_var)) PGV { // \
|
|
// expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
|
|
};
|
|
|
|
int *pgv_var_args __attribute__((pt_guarded_var(1))); // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
|
|
|
|
void pgv_function() __attribute__((pt_guarded_var)); // \
|
|
// expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
|
|
|
|
void pgv_function_params(int *gv_lvar __attribute__((pt_guarded_var))); // \
|
|
// expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
|
|
|
|
void pgv_testfn(int y){
|
|
int *x __attribute__((pt_guarded_var)) = new int(0); // \
|
|
// expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
|
|
delete x;
|
|
}
|
|
|
|
//-----------------------------------------//
|
|
// Lockable Attribute (l)
|
|
//-----------------------------------------//
|
|
|
|
//FIXME: In future we may want to add support for structs, ObjC classes, etc.
|
|
|
|
#if !__has_attribute(lockable)
|
|
#error "Should support lockable attribute"
|
|
#endif
|
|
|
|
class __attribute__((lockable)) LTestClass {
|
|
};
|
|
|
|
class __attribute__((lockable (1))) LTestClass_args { // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
};
|
|
|
|
void l_test_function() __attribute__((lockable)); // \
|
|
// expected-warning {{'lockable' attribute only applies to classes}}
|
|
|
|
int l_testfn(int y) {
|
|
int x __attribute__((lockable)) = y; // \
|
|
// expected-warning {{'lockable' attribute only applies to classes}}
|
|
return x;
|
|
}
|
|
|
|
int l_test_var __attribute__((lockable)); // \
|
|
// expected-warning {{'lockable' attribute only applies to classes}}
|
|
|
|
class LFoo {
|
|
private:
|
|
int test_field __attribute__((lockable)); // \
|
|
// expected-warning {{'lockable' attribute only applies to classes}}
|
|
void test_method() __attribute__((lockable)); // \
|
|
// expected-warning {{'lockable' attribute only applies to classes}}
|
|
};
|
|
|
|
|
|
void l_function_params(int lvar __attribute__((lockable))); // \
|
|
// expected-warning {{'lockable' attribute only applies to classes}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Scoped Lockable Attribute (sl)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(scoped_lockable)
|
|
#error "Should support scoped_lockable attribute"
|
|
#endif
|
|
|
|
class __attribute__((scoped_lockable)) SLTestClass {
|
|
};
|
|
|
|
class __attribute__((scoped_lockable (1))) SLTestClass_args { // \
|
|
// expected-error {{attribute takes no arguments}}
|
|
};
|
|
|
|
void sl_test_function() __attribute__((scoped_lockable)); // \
|
|
// expected-warning {{'scoped_lockable' attribute only applies to classes}}
|
|
|
|
int sl_testfn(int y) {
|
|
int x __attribute__((scoped_lockable)) = y; // \
|
|
// expected-warning {{'scoped_lockable' attribute only applies to classes}}
|
|
return x;
|
|
}
|
|
|
|
int sl_test_var __attribute__((scoped_lockable)); // \
|
|
// expected-warning {{'scoped_lockable' attribute only applies to classes}}
|
|
|
|
class SLFoo {
|
|
private:
|
|
int test_field __attribute__((scoped_lockable)); // \
|
|
// expected-warning {{'scoped_lockable' attribute only applies to classes}}
|
|
void test_method() __attribute__((scoped_lockable)); // \
|
|
// expected-warning {{'scoped_lockable' attribute only applies to classes}}
|
|
};
|
|
|
|
|
|
void sl_function_params(int lvar __attribute__((scoped_lockable))); // \
|
|
// expected-warning {{'scoped_lockable' attribute only applies to classes}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Guarded By Attribute (gb)
|
|
//-----------------------------------------//
|
|
|
|
// FIXME: Eventually, would we like this attribute to take more than 1 arg?
|
|
|
|
#if !__has_attribute(guarded_by)
|
|
#error "Should support guarded_by attribute"
|
|
#endif
|
|
|
|
//1. Check applied to the right types & argument number
|
|
|
|
int gb_var_arg __attribute__((guarded_by(mu1)));
|
|
|
|
int gb_var_args __attribute__((guarded_by(mu1, mu2))); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
|
|
int gb_var_noargs __attribute__((guarded_by)); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
|
|
class GBFoo {
|
|
private:
|
|
int gb_field_noargs __attribute__((guarded_by)); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
int gb_field_args __attribute__((guarded_by(mu1)));
|
|
};
|
|
|
|
class __attribute__((guarded_by(mu1))) GB { // \
|
|
// expected-warning {{'guarded_by' attribute only applies to fields and global variables}}
|
|
};
|
|
|
|
void gb_function() __attribute__((guarded_by(mu1))); // \
|
|
// expected-warning {{'guarded_by' attribute only applies to fields and global variables}}
|
|
|
|
void gb_function_params(int gv_lvar __attribute__((guarded_by(mu1)))); // \
|
|
// expected-warning {{'guarded_by' attribute only applies to fields and global variables}}
|
|
|
|
int gb_testfn(int y){
|
|
int x __attribute__((guarded_by(mu1))) = y; // \
|
|
// expected-warning {{'guarded_by' attribute only applies to fields and global variables}}
|
|
return x;
|
|
}
|
|
|
|
//2. Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int gb_var_arg_1 __attribute__((guarded_by(muWrapper.mu)));
|
|
int gb_var_arg_2 __attribute__((guarded_by(muDoubleWrapper.muWrapper->mu)));
|
|
int gb_var_arg_3 __attribute__((guarded_by(muWrapper.getMu())));
|
|
int gb_var_arg_4 __attribute__((guarded_by(*muWrapper.getMuPointer())));
|
|
int gb_var_arg_5 __attribute__((guarded_by(&mu1)));
|
|
int gb_var_arg_6 __attribute__((guarded_by(muRef)));
|
|
int gb_var_arg_7 __attribute__((guarded_by(muDoubleWrapper.getWrapper()->getMu())));
|
|
int gb_var_arg_8 __attribute__((guarded_by(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \
|
|
// expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}}
|
|
int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \
|
|
// expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}}
|
|
int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \
|
|
// expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}}
|
|
int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \
|
|
// expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}}
|
|
|
|
//3.
|
|
// Thread Safety analysis tests
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Pt Guarded By Attribute (pgb)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(pt_guarded_by)
|
|
#error "Should support pt_guarded_by attribute"
|
|
#endif
|
|
|
|
//1. Check applied to the right types & argument number
|
|
|
|
int *pgb_var_noargs __attribute__((pt_guarded_by)); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
|
|
int *pgb_ptr_var_arg __attribute__((pt_guarded_by(mu1)));
|
|
|
|
int *pgb_ptr_var_args __attribute__((guarded_by(mu1, mu2))); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
|
|
int pgb_var_args __attribute__((pt_guarded_by(mu1))); // \
|
|
// expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}
|
|
|
|
class PGBFoo {
|
|
private:
|
|
int *pgb_field_noargs __attribute__((pt_guarded_by)); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
int *pgb_field_args __attribute__((pt_guarded_by(mu1)));
|
|
};
|
|
|
|
class __attribute__((pt_guarded_by(mu1))) PGB { // \
|
|
// expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
|
|
};
|
|
|
|
void pgb_function() __attribute__((pt_guarded_by(mu1))); // \
|
|
// expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
|
|
|
|
void pgb_function_params(int gv_lvar __attribute__((pt_guarded_by(mu1)))); // \
|
|
// expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
|
|
|
|
void pgb_testfn(int y){
|
|
int *x __attribute__((pt_guarded_by(mu1))) = new int(0); // \
|
|
// expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
|
|
delete x;
|
|
}
|
|
|
|
//2. Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int * pgb_var_arg_1 __attribute__((pt_guarded_by(muWrapper.mu)));
|
|
int * pgb_var_arg_2 __attribute__((pt_guarded_by(muDoubleWrapper.muWrapper->mu)));
|
|
int * pgb_var_arg_3 __attribute__((pt_guarded_by(muWrapper.getMu())));
|
|
int * pgb_var_arg_4 __attribute__((pt_guarded_by(*muWrapper.getMuPointer())));
|
|
int * pgb_var_arg_5 __attribute__((pt_guarded_by(&mu1)));
|
|
int * pgb_var_arg_6 __attribute__((pt_guarded_by(muRef)));
|
|
int * pgb_var_arg_7 __attribute__((pt_guarded_by(muDoubleWrapper.getWrapper()->getMu())));
|
|
int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \
|
|
// expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
|
|
int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \
|
|
// expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
|
|
int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \
|
|
// expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
|
|
int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \
|
|
// expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Acquired After (aa)
|
|
//-----------------------------------------//
|
|
|
|
// FIXME: Would we like this attribute to take more than 1 arg?
|
|
|
|
#if !__has_attribute(acquired_after)
|
|
#error "Should support acquired_after attribute"
|
|
#endif
|
|
|
|
Mu mu_aa __attribute__((acquired_after(mu1)));
|
|
|
|
Mu aa_var_noargs __attribute__((acquired_after)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
class AAFoo {
|
|
private:
|
|
Mu aa_field_noargs __attribute__((acquired_after)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
Mu aa_field_args __attribute__((acquired_after(mu1)));
|
|
};
|
|
|
|
class __attribute__((acquired_after(mu1))) AA { // \
|
|
// expected-warning {{'acquired_after' attribute only applies to fields and global variables}}
|
|
};
|
|
|
|
void aa_function() __attribute__((acquired_after(mu1))); // \
|
|
// expected-warning {{'acquired_after' attribute only applies to fields and global variables}}
|
|
|
|
void aa_function_params(int gv_lvar __attribute__((acquired_after(mu1)))); // \
|
|
// expected-warning {{'acquired_after' attribute only applies to fields and global variables}}
|
|
|
|
void aa_testfn(int y){
|
|
Mu x __attribute__((acquired_after(mu1))) = Mu(); // \
|
|
// expected-warning {{'acquired_after' attribute only applies to fields and global variables}}
|
|
}
|
|
|
|
//Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
Mu aa_var_arg_1 __attribute__((acquired_after(muWrapper.mu)));
|
|
Mu aa_var_arg_2 __attribute__((acquired_after(muDoubleWrapper.muWrapper->mu)));
|
|
Mu aa_var_arg_3 __attribute__((acquired_after(muWrapper.getMu())));
|
|
Mu aa_var_arg_4 __attribute__((acquired_after(*muWrapper.getMuPointer())));
|
|
Mu aa_var_arg_5 __attribute__((acquired_after(&mu1)));
|
|
Mu aa_var_arg_6 __attribute__((acquired_after(muRef)));
|
|
Mu aa_var_arg_7 __attribute__((acquired_after(muDoubleWrapper.getWrapper()->getMu())));
|
|
Mu aa_var_arg_8 __attribute__((acquired_after(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \
|
|
// expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}}
|
|
Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \
|
|
// expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}}
|
|
Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \
|
|
// expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}}
|
|
Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \
|
|
// expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \
|
|
// expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}}
|
|
|
|
//-----------------------------------------//
|
|
// Acquired Before (ab)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(acquired_before)
|
|
#error "Should support acquired_before attribute"
|
|
#endif
|
|
|
|
Mu mu_ab __attribute__((acquired_before(mu1)));
|
|
|
|
Mu ab_var_noargs __attribute__((acquired_before)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
class ABFoo {
|
|
private:
|
|
Mu ab_field_noargs __attribute__((acquired_before)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
Mu ab_field_args __attribute__((acquired_before(mu1)));
|
|
};
|
|
|
|
class __attribute__((acquired_before(mu1))) AB { // \
|
|
// expected-warning {{'acquired_before' attribute only applies to fields and global variables}}
|
|
};
|
|
|
|
void ab_function() __attribute__((acquired_before(mu1))); // \
|
|
// expected-warning {{'acquired_before' attribute only applies to fields and global variables}}
|
|
|
|
void ab_function_params(int gv_lvar __attribute__((acquired_before(mu1)))); // \
|
|
// expected-warning {{'acquired_before' attribute only applies to fields and global variables}}
|
|
|
|
void ab_testfn(int y){
|
|
Mu x __attribute__((acquired_before(mu1))) = Mu(); // \
|
|
// expected-warning {{'acquired_before' attribute only applies to fields and global variables}}
|
|
}
|
|
|
|
// Note: illegal int ab_int __attribute__((acquired_before(mu1))) will
|
|
// be taken care of by warnings that ab__int is not lockable.
|
|
|
|
//Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
Mu ab_var_arg_1 __attribute__((acquired_before(muWrapper.mu)));
|
|
Mu ab_var_arg_2 __attribute__((acquired_before(muDoubleWrapper.muWrapper->mu)));
|
|
Mu ab_var_arg_3 __attribute__((acquired_before(muWrapper.getMu())));
|
|
Mu ab_var_arg_4 __attribute__((acquired_before(*muWrapper.getMuPointer())));
|
|
Mu ab_var_arg_5 __attribute__((acquired_before(&mu1)));
|
|
Mu ab_var_arg_6 __attribute__((acquired_before(muRef)));
|
|
Mu ab_var_arg_7 __attribute__((acquired_before(muDoubleWrapper.getWrapper()->getMu())));
|
|
Mu ab_var_arg_8 __attribute__((acquired_before(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \
|
|
// expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}}
|
|
Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \
|
|
// expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}}
|
|
Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \
|
|
// expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}}
|
|
Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \
|
|
// expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \
|
|
// expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Exclusive Lock Function (elf)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(exclusive_lock_function)
|
|
#error "Should support exclusive_lock_function attribute"
|
|
#endif
|
|
|
|
// takes zero or more arguments, all locks (vars/fields)
|
|
|
|
void elf_function() __attribute__((exclusive_lock_function));
|
|
|
|
void elf_function_args() __attribute__((exclusive_lock_function(mu1, mu2)));
|
|
|
|
int elf_testfn(int y) __attribute__((exclusive_lock_function));
|
|
|
|
int elf_testfn(int y) {
|
|
int x __attribute__((exclusive_lock_function)) = y; // \
|
|
// expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int elf_test_var __attribute__((exclusive_lock_function)); // \
|
|
// expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}}
|
|
|
|
class ElfFoo {
|
|
private:
|
|
int test_field __attribute__((exclusive_lock_function)); // \
|
|
// expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((exclusive_lock_function));
|
|
};
|
|
|
|
class __attribute__((exclusive_lock_function)) ElfTestClass { // \
|
|
// expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
void elf_fun_params(int lvar __attribute__((exclusive_lock_function))); // \
|
|
// expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}}
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int elf_function_1() __attribute__((exclusive_lock_function(muWrapper.mu)));
|
|
int elf_function_2() __attribute__((exclusive_lock_function(muDoubleWrapper.muWrapper->mu)));
|
|
int elf_function_3() __attribute__((exclusive_lock_function(muWrapper.getMu())));
|
|
int elf_function_4() __attribute__((exclusive_lock_function(*muWrapper.getMuPointer())));
|
|
int elf_function_5() __attribute__((exclusive_lock_function(&mu1)));
|
|
int elf_function_6() __attribute__((exclusive_lock_function(muRef)));
|
|
int elf_function_7() __attribute__((exclusive_lock_function(muDoubleWrapper.getWrapper()->getMu())));
|
|
int elf_function_8() __attribute__((exclusive_lock_function(muPointer)));
|
|
int elf_function_9(Mu x) __attribute__((exclusive_lock_function(1)));
|
|
int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \
|
|
// expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
|
|
int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \
|
|
// expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
|
|
int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \
|
|
// expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \
|
|
// expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
|
int elf_function_bad_5(Mu x) __attribute__((exclusive_lock_function(0))); // \
|
|
// expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}}
|
|
int elf_function_bad_6(Mu x, Mu y) __attribute__((exclusive_lock_function(0))); // \
|
|
// expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}}
|
|
int elf_function_bad_7() __attribute__((exclusive_lock_function(0))); // \
|
|
// expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Shared Lock Function (slf)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(shared_lock_function)
|
|
#error "Should support shared_lock_function attribute"
|
|
#endif
|
|
|
|
// takes zero or more arguments, all locks (vars/fields)
|
|
|
|
void slf_function() __attribute__((shared_lock_function));
|
|
|
|
void slf_function_args() __attribute__((shared_lock_function(mu1, mu2)));
|
|
|
|
int slf_testfn(int y) __attribute__((shared_lock_function));
|
|
|
|
int slf_testfn(int y) {
|
|
int x __attribute__((shared_lock_function)) = y; // \
|
|
// expected-warning {{'shared_lock_function' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int slf_test_var __attribute__((shared_lock_function)); // \
|
|
// expected-warning {{'shared_lock_function' attribute only applies to functions and methods}}
|
|
|
|
void slf_fun_params(int lvar __attribute__((shared_lock_function))); // \
|
|
// expected-warning {{'shared_lock_function' attribute only applies to functions and methods}}
|
|
|
|
class SlfFoo {
|
|
private:
|
|
int test_field __attribute__((shared_lock_function)); // \
|
|
// expected-warning {{'shared_lock_function' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((shared_lock_function));
|
|
};
|
|
|
|
class __attribute__((shared_lock_function)) SlfTestClass { // \
|
|
// expected-warning {{'shared_lock_function' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int slf_function_1() __attribute__((shared_lock_function(muWrapper.mu)));
|
|
int slf_function_2() __attribute__((shared_lock_function(muDoubleWrapper.muWrapper->mu)));
|
|
int slf_function_3() __attribute__((shared_lock_function(muWrapper.getMu())));
|
|
int slf_function_4() __attribute__((shared_lock_function(*muWrapper.getMuPointer())));
|
|
int slf_function_5() __attribute__((shared_lock_function(&mu1)));
|
|
int slf_function_6() __attribute__((shared_lock_function(muRef)));
|
|
int slf_function_7() __attribute__((shared_lock_function(muDoubleWrapper.getWrapper()->getMu())));
|
|
int slf_function_8() __attribute__((shared_lock_function(muPointer)));
|
|
int slf_function_9(Mu x) __attribute__((shared_lock_function(1)));
|
|
int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \
|
|
// expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
|
|
int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \
|
|
// expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
|
|
int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \
|
|
// expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \
|
|
// expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
|
int slf_function_bad_5(Mu x) __attribute__((shared_lock_function(0))); // \
|
|
// expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}}
|
|
int slf_function_bad_6(Mu x, Mu y) __attribute__((shared_lock_function(0))); // \
|
|
// expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}}
|
|
int slf_function_bad_7() __attribute__((shared_lock_function(0))); // \
|
|
// expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Exclusive TryLock Function (etf)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(exclusive_trylock_function)
|
|
#error "Should support exclusive_trylock_function attribute"
|
|
#endif
|
|
|
|
// takes a mandatory boolean or integer argument specifying the retval
|
|
// plus an optional list of locks (vars/fields)
|
|
|
|
void etf_function() __attribute__((exclusive_trylock_function)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
void etf_function_args() __attribute__((exclusive_trylock_function(1, mu2)));
|
|
|
|
void etf_function_arg() __attribute__((exclusive_trylock_function(1)));
|
|
|
|
int etf_testfn(int y) __attribute__((exclusive_trylock_function(1)));
|
|
|
|
int etf_testfn(int y) {
|
|
int x __attribute__((exclusive_trylock_function(1))) = y; // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int etf_test_var __attribute__((exclusive_trylock_function(1))); // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}}
|
|
|
|
class EtfFoo {
|
|
private:
|
|
int test_field __attribute__((exclusive_trylock_function(1))); // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((exclusive_trylock_function(1)));
|
|
};
|
|
|
|
class __attribute__((exclusive_trylock_function(1))) EtfTestClass { // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
void etf_fun_params(int lvar __attribute__((exclusive_trylock_function(1)))); // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}}
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int etf_function_1() __attribute__((exclusive_trylock_function(1, muWrapper.mu)));
|
|
int etf_function_2() __attribute__((exclusive_trylock_function(1, muDoubleWrapper.muWrapper->mu)));
|
|
int etf_function_3() __attribute__((exclusive_trylock_function(1, muWrapper.getMu())));
|
|
int etf_function_4() __attribute__((exclusive_trylock_function(1, *muWrapper.getMuPointer())));
|
|
int etf_function_5() __attribute__((exclusive_trylock_function(1, &mu1)));
|
|
int etf_function_6() __attribute__((exclusive_trylock_function(1, muRef)));
|
|
int etf_function_7() __attribute__((exclusive_trylock_function(1, muDoubleWrapper.getWrapper()->getMu())));
|
|
int etf_functetfn_8() __attribute__((exclusive_trylock_function(1, muPointer)));
|
|
int etf_function_9() __attribute__((exclusive_trylock_function(true)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int etf_function_bad_1() __attribute__((exclusive_trylock_function(mu1))); // \
|
|
// expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
|
|
int etf_function_bad_2() __attribute__((exclusive_trylock_function("mu"))); // \
|
|
// expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
|
|
int etf_function_bad_3() __attribute__((exclusive_trylock_function(muDoublePointer))); // \
|
|
// expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
|
|
|
|
int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
|
|
int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
|
|
int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \
|
|
// expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Shared TryLock Function (stf)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(shared_trylock_function)
|
|
#error "Should support shared_trylock_function attribute"
|
|
#endif
|
|
|
|
// takes a mandatory boolean or integer argument specifying the retval
|
|
// plus an optional list of locks (vars/fields)
|
|
|
|
void stf_function() __attribute__((shared_trylock_function)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
void stf_function_args() __attribute__((shared_trylock_function(1, mu2)));
|
|
|
|
void stf_function_arg() __attribute__((shared_trylock_function(1)));
|
|
|
|
int stf_testfn(int y) __attribute__((shared_trylock_function(1)));
|
|
|
|
int stf_testfn(int y) {
|
|
int x __attribute__((shared_trylock_function(1))) = y; // \
|
|
// expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int stf_test_var __attribute__((shared_trylock_function(1))); // \
|
|
// expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}}
|
|
|
|
void stf_fun_params(int lvar __attribute__((shared_trylock_function(1)))); // \
|
|
// expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}}
|
|
|
|
|
|
class StfFoo {
|
|
private:
|
|
int test_field __attribute__((shared_trylock_function(1))); // \
|
|
// expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((shared_trylock_function(1)));
|
|
};
|
|
|
|
class __attribute__((shared_trylock_function(1))) StfTestClass { // \
|
|
// expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int stf_function_1() __attribute__((shared_trylock_function(1, muWrapper.mu)));
|
|
int stf_function_2() __attribute__((shared_trylock_function(1, muDoubleWrapper.muWrapper->mu)));
|
|
int stf_function_3() __attribute__((shared_trylock_function(1, muWrapper.getMu())));
|
|
int stf_function_4() __attribute__((shared_trylock_function(1, *muWrapper.getMuPointer())));
|
|
int stf_function_5() __attribute__((shared_trylock_function(1, &mu1)));
|
|
int stf_function_6() __attribute__((shared_trylock_function(1, muRef)));
|
|
int stf_function_7() __attribute__((shared_trylock_function(1, muDoubleWrapper.getWrapper()->getMu())));
|
|
int stf_function_8() __attribute__((shared_trylock_function(1, muPointer)));
|
|
int stf_function_9() __attribute__((shared_trylock_function(true)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int stf_function_bad_1() __attribute__((shared_trylock_function(mu1))); // \
|
|
// expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
|
|
int stf_function_bad_2() __attribute__((shared_trylock_function("mu"))); // \
|
|
// expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
|
|
int stf_function_bad_3() __attribute__((shared_trylock_function(muDoublePointer))); // \
|
|
// expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
|
|
|
|
int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \
|
|
// expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
|
|
int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \
|
|
// expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
|
|
int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \
|
|
// expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Unlock Function (uf)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(unlock_function)
|
|
#error "Should support unlock_function attribute"
|
|
#endif
|
|
|
|
// takes zero or more arguments, all locks (vars/fields)
|
|
|
|
void uf_function() __attribute__((unlock_function));
|
|
|
|
void uf_function_args() __attribute__((unlock_function(mu1, mu2)));
|
|
|
|
int uf_testfn(int y) __attribute__((unlock_function));
|
|
|
|
int uf_testfn(int y) {
|
|
int x __attribute__((unlock_function)) = y; // \
|
|
// expected-warning {{'unlock_function' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int uf_test_var __attribute__((unlock_function)); // \
|
|
// expected-warning {{'unlock_function' attribute only applies to functions and methods}}
|
|
|
|
class UfFoo {
|
|
private:
|
|
int test_field __attribute__((unlock_function)); // \
|
|
// expected-warning {{'unlock_function' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((unlock_function));
|
|
};
|
|
|
|
class __attribute__((no_thread_safety_analysis)) UfTestClass { // \
|
|
// expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
void uf_fun_params(int lvar __attribute__((unlock_function))); // \
|
|
// expected-warning {{'unlock_function' attribute only applies to functions and methods}}
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int uf_function_1() __attribute__((unlock_function(muWrapper.mu)));
|
|
int uf_function_2() __attribute__((unlock_function(muDoubleWrapper.muWrapper->mu)));
|
|
int uf_function_3() __attribute__((unlock_function(muWrapper.getMu())));
|
|
int uf_function_4() __attribute__((unlock_function(*muWrapper.getMuPointer())));
|
|
int uf_function_5() __attribute__((unlock_function(&mu1)));
|
|
int uf_function_6() __attribute__((unlock_function(muRef)));
|
|
int uf_function_7() __attribute__((unlock_function(muDoubleWrapper.getWrapper()->getMu())));
|
|
int uf_function_8() __attribute__((unlock_function(muPointer)));
|
|
int uf_function_9(Mu x) __attribute__((unlock_function(1)));
|
|
int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \
|
|
// expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}}
|
|
int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \
|
|
// expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}}
|
|
int uf_function_bad_4() __attribute__((unlock_function(umu))); // \
|
|
// expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
int uf_function_bad_1() __attribute__((unlock_function(1))); // \
|
|
// expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
|
int uf_function_bad_5(Mu x) __attribute__((unlock_function(0))); // \
|
|
// expected-error {{'unlock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}}
|
|
int uf_function_bad_6(Mu x, Mu y) __attribute__((unlock_function(0))); // \
|
|
// expected-error {{'unlock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}}
|
|
int uf_function_bad_7() __attribute__((unlock_function(0))); // \
|
|
// expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Lock Returned (lr)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(lock_returned)
|
|
#error "Should support lock_returned attribute"
|
|
#endif
|
|
|
|
// Takes exactly one argument, a var/field
|
|
|
|
void lr_function() __attribute__((lock_returned)); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
|
|
void lr_function_arg() __attribute__((lock_returned(mu1)));
|
|
|
|
void lr_function_args() __attribute__((lock_returned(mu1, mu2))); // \
|
|
// expected-error {{attribute takes one argument}}
|
|
|
|
int lr_testfn(int y) __attribute__((lock_returned(mu1)));
|
|
|
|
int lr_testfn(int y) {
|
|
int x __attribute__((lock_returned(mu1))) = y; // \
|
|
// expected-warning {{'lock_returned' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int lr_test_var __attribute__((lock_returned(mu1))); // \
|
|
// expected-warning {{'lock_returned' attribute only applies to functions and methods}}
|
|
|
|
void lr_fun_params(int lvar __attribute__((lock_returned(mu1)))); // \
|
|
// expected-warning {{'lock_returned' attribute only applies to functions and methods}}
|
|
|
|
class LrFoo {
|
|
private:
|
|
int test_field __attribute__((lock_returned(mu1))); // \
|
|
// expected-warning {{'lock_returned' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((lock_returned(mu1)));
|
|
};
|
|
|
|
class __attribute__((lock_returned(mu1))) LrTestClass { // \
|
|
// expected-warning {{'lock_returned' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int lr_function_1() __attribute__((lock_returned(muWrapper.mu)));
|
|
int lr_function_2() __attribute__((lock_returned(muDoubleWrapper.muWrapper->mu)));
|
|
int lr_function_3() __attribute__((lock_returned(muWrapper.getMu())));
|
|
int lr_function_4() __attribute__((lock_returned(*muWrapper.getMuPointer())));
|
|
int lr_function_5() __attribute__((lock_returned(&mu1)));
|
|
int lr_function_6() __attribute__((lock_returned(muRef)));
|
|
int lr_function_7() __attribute__((lock_returned(muDoubleWrapper.getWrapper()->getMu())));
|
|
int lr_function_8() __attribute__((lock_returned(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int lr_function_bad_1() __attribute__((lock_returned(1))); // \
|
|
// expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
|
int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \
|
|
// expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
|
int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \
|
|
// expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
|
int lr_function_bad_4() __attribute__((lock_returned(umu))); // \
|
|
// expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Locks Excluded (le)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(locks_excluded)
|
|
#error "Should support locks_excluded attribute"
|
|
#endif
|
|
|
|
// takes one or more arguments, all locks (vars/fields)
|
|
|
|
void le_function() __attribute__((locks_excluded)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
void le_function_arg() __attribute__((locks_excluded(mu1)));
|
|
|
|
void le_function_args() __attribute__((locks_excluded(mu1, mu2)));
|
|
|
|
int le_testfn(int y) __attribute__((locks_excluded(mu1)));
|
|
|
|
int le_testfn(int y) {
|
|
int x __attribute__((locks_excluded(mu1))) = y; // \
|
|
// expected-warning {{'locks_excluded' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int le_test_var __attribute__((locks_excluded(mu1))); // \
|
|
// expected-warning {{'locks_excluded' attribute only applies to functions and methods}}
|
|
|
|
void le_fun_params(int lvar __attribute__((locks_excluded(mu1)))); // \
|
|
// expected-warning {{'locks_excluded' attribute only applies to functions and methods}}
|
|
|
|
class LeFoo {
|
|
private:
|
|
int test_field __attribute__((locks_excluded(mu1))); // \
|
|
// expected-warning {{'locks_excluded' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((locks_excluded(mu1)));
|
|
};
|
|
|
|
class __attribute__((locks_excluded(mu1))) LeTestClass { // \
|
|
// expected-warning {{'locks_excluded' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int le_function_1() __attribute__((locks_excluded(muWrapper.mu)));
|
|
int le_function_2() __attribute__((locks_excluded(muDoubleWrapper.muWrapper->mu)));
|
|
int le_function_3() __attribute__((locks_excluded(muWrapper.getMu())));
|
|
int le_function_4() __attribute__((locks_excluded(*muWrapper.getMuPointer())));
|
|
int le_function_5() __attribute__((locks_excluded(&mu1)));
|
|
int le_function_6() __attribute__((locks_excluded(muRef)));
|
|
int le_function_7() __attribute__((locks_excluded(muDoubleWrapper.getWrapper()->getMu())));
|
|
int le_function_8() __attribute__((locks_excluded(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int le_function_bad_1() __attribute__((locks_excluded(1))); // \
|
|
// expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
|
|
int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \
|
|
// expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
|
|
int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \
|
|
// expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
|
|
int le_function_bad_4() __attribute__((locks_excluded(umu))); // \
|
|
// expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Exclusive Locks Required (elr)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(exclusive_locks_required)
|
|
#error "Should support exclusive_locks_required attribute"
|
|
#endif
|
|
|
|
// takes one or more arguments, all locks (vars/fields)
|
|
|
|
void elr_function() __attribute__((exclusive_locks_required)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
void elr_function_arg() __attribute__((exclusive_locks_required(mu1)));
|
|
|
|
void elr_function_args() __attribute__((exclusive_locks_required(mu1, mu2)));
|
|
|
|
int elr_testfn(int y) __attribute__((exclusive_locks_required(mu1)));
|
|
|
|
int elr_testfn(int y) {
|
|
int x __attribute__((exclusive_locks_required(mu1))) = y; // \
|
|
// expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int elr_test_var __attribute__((exclusive_locks_required(mu1))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}}
|
|
|
|
void elr_fun_params(int lvar __attribute__((exclusive_locks_required(mu1)))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}}
|
|
|
|
class ElrFoo {
|
|
private:
|
|
int test_field __attribute__((exclusive_locks_required(mu1))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((exclusive_locks_required(mu1)));
|
|
};
|
|
|
|
class __attribute__((exclusive_locks_required(mu1))) ElrTestClass { // \
|
|
// expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int elr_function_1() __attribute__((exclusive_locks_required(muWrapper.mu)));
|
|
int elr_function_2() __attribute__((exclusive_locks_required(muDoubleWrapper.muWrapper->mu)));
|
|
int elr_function_3() __attribute__((exclusive_locks_required(muWrapper.getMu())));
|
|
int elr_function_4() __attribute__((exclusive_locks_required(*muWrapper.getMuPointer())));
|
|
int elr_function_5() __attribute__((exclusive_locks_required(&mu1)));
|
|
int elr_function_6() __attribute__((exclusive_locks_required(muRef)));
|
|
int elr_function_7() __attribute__((exclusive_locks_required(muDoubleWrapper.getWrapper()->getMu())));
|
|
int elr_function_8() __attribute__((exclusive_locks_required(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
|
|
int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
|
|
int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
|
|
int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \
|
|
// expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Shared Locks Required (slr)
|
|
//-----------------------------------------//
|
|
|
|
#if !__has_attribute(shared_locks_required)
|
|
#error "Should support shared_locks_required attribute"
|
|
#endif
|
|
|
|
// takes one or more arguments, all locks (vars/fields)
|
|
|
|
void slr_function() __attribute__((shared_locks_required)); // \
|
|
// expected-error {{attribute takes at least 1 argument}}
|
|
|
|
void slr_function_arg() __attribute__((shared_locks_required(mu1)));
|
|
|
|
void slr_function_args() __attribute__((shared_locks_required(mu1, mu2)));
|
|
|
|
int slr_testfn(int y) __attribute__((shared_locks_required(mu1)));
|
|
|
|
int slr_testfn(int y) {
|
|
int x __attribute__((shared_locks_required(mu1))) = y; // \
|
|
// expected-warning {{'shared_locks_required' attribute only applies to functions and methods}}
|
|
return x;
|
|
};
|
|
|
|
int slr_test_var __attribute__((shared_locks_required(mu1))); // \
|
|
// expected-warning {{'shared_locks_required' attribute only applies to functions and methods}}
|
|
|
|
void slr_fun_params(int lvar __attribute__((shared_locks_required(mu1)))); // \
|
|
// expected-warning {{'shared_locks_required' attribute only applies to functions and methods}}
|
|
|
|
class SlrFoo {
|
|
private:
|
|
int test_field __attribute__((shared_locks_required(mu1))); // \
|
|
// expected-warning {{'shared_locks_required' attribute only applies to functions and methods}}
|
|
void test_method() __attribute__((shared_locks_required(mu1)));
|
|
};
|
|
|
|
class __attribute__((shared_locks_required(mu1))) SlrTestClass { // \
|
|
// expected-warning {{'shared_locks_required' attribute only applies to functions and methods}}
|
|
};
|
|
|
|
// Check argument parsing.
|
|
|
|
// legal attribute arguments
|
|
int slr_function_1() __attribute__((shared_locks_required(muWrapper.mu)));
|
|
int slr_function_2() __attribute__((shared_locks_required(muDoubleWrapper.muWrapper->mu)));
|
|
int slr_function_3() __attribute__((shared_locks_required(muWrapper.getMu())));
|
|
int slr_function_4() __attribute__((shared_locks_required(*muWrapper.getMuPointer())));
|
|
int slr_function_5() __attribute__((shared_locks_required(&mu1)));
|
|
int slr_function_6() __attribute__((shared_locks_required(muRef)));
|
|
int slr_function_7() __attribute__((shared_locks_required(muDoubleWrapper.getWrapper()->getMu())));
|
|
int slr_function_8() __attribute__((shared_locks_required(muPointer)));
|
|
|
|
|
|
// illegal attribute arguments
|
|
int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \
|
|
// expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
|
|
int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \
|
|
// expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
|
|
int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \
|
|
// expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
|
|
int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \
|
|
// expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
|
|
|
|
|
//-----------------------------------------//
|
|
// Regression tests for unusual cases.
|
|
//-----------------------------------------//
|
|
|
|
int trivially_false_edges(bool b) {
|
|
// Create NULL (never taken) edges in CFG
|
|
if (false) return 1;
|
|
else return 2;
|
|
}
|
|
|
|
// Possible Clang bug -- method pointer in template parameter
|
|
class UnFoo {
|
|
public:
|
|
void foo();
|
|
};
|
|
|
|
template<void (UnFoo::*methptr)()>
|
|
class MCaller {
|
|
public:
|
|
static void call_method_ptr(UnFoo *f) {
|
|
// FIXME: Possible Clang bug:
|
|
// getCalleeDecl() returns NULL in the following case:
|
|
(f->*methptr)();
|
|
}
|
|
};
|
|
|
|
void call_method_ptr_inst(UnFoo* f) {
|
|
MCaller<&UnFoo::foo>::call_method_ptr(f);
|
|
}
|
|
|
|
int temp;
|
|
void empty_back_edge() {
|
|
// Create a back edge to a block with with no statements
|
|
for (;;) {
|
|
++temp;
|
|
if (temp > 10) break;
|
|
}
|
|
}
|
|
|
|
struct Foomger {
|
|
void operator++();
|
|
};
|
|
|
|
struct Foomgoper {
|
|
Foomger f;
|
|
|
|
bool done();
|
|
void invalid_back_edge() {
|
|
do {
|
|
// FIXME: Possible Clang bug:
|
|
// The first statement in this basic block has no source location
|
|
++f;
|
|
} while (!done());
|
|
}
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------
|
|
// Parsing of member variables and function parameters
|
|
//------------------------------------------------------
|
|
|
|
Mu gmu;
|
|
|
|
class StaticMu {
|
|
static Mu statmu;
|
|
};
|
|
|
|
class FooLate {
|
|
public:
|
|
void foo1() __attribute__((exclusive_locks_required(gmu))) { }
|
|
void foo2() __attribute__((exclusive_locks_required(mu))) { }
|
|
void foo3(Mu *m) __attribute__((exclusive_locks_required(m))) { }
|
|
void foo3(FooLate *f) __attribute__((exclusive_locks_required(f->mu))) { }
|
|
void foo4(FooLate *f) __attribute__((exclusive_locks_required(f->mu)));
|
|
|
|
static void foo5() __attribute__((exclusive_locks_required(mu))); // \
|
|
// expected-error {{'this' cannot be implicitly used in a static member function declaration}}
|
|
|
|
template <class T>
|
|
void foo6() __attribute__((exclusive_locks_required(T::statmu))) { }
|
|
|
|
template <class T>
|
|
void foo7(T* f) __attribute__((exclusive_locks_required(f->mu))) { }
|
|
|
|
int a __attribute__((guarded_by(gmu)));
|
|
int b __attribute__((guarded_by(mu)));
|
|
int c __attribute__((guarded_by(this->mu)));
|
|
|
|
Mu mu;
|
|
};
|
|
|
|
//-------------------------
|
|
// Empty argument lists
|
|
//-------------------------
|
|
|
|
class __attribute__((lockable)) EmptyArgListsTest {
|
|
void lock() __attribute__((exclusive_lock_function())) { }
|
|
void unlock() __attribute__((unlock_function())) { }
|
|
};
|
|
|
|
|
|
namespace FunctionDefinitionParseTest {
|
|
// Test parsing of attributes on function definitions.
|
|
|
|
class Foo {
|
|
public:
|
|
Mu mu_;
|
|
void foo1();
|
|
void foo2(Foo *f);
|
|
};
|
|
|
|
template <class T>
|
|
class Bar {
|
|
public:
|
|
Mu mu_;
|
|
void bar();
|
|
};
|
|
|
|
void Foo::foo1() __attribute__((exclusive_locks_required(mu_))) { }
|
|
void Foo::foo2(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { }
|
|
|
|
template <class T>
|
|
void Bar<T>::bar() __attribute__((exclusive_locks_required(mu_))) { }
|
|
|
|
void baz(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { }
|
|
|
|
} // end namespace
|
|
|
|
|
|
namespace TestMultiDecl {
|
|
|
|
class Foo {
|
|
public:
|
|
int __attribute__((guarded_by(mu_))) a;
|
|
int __attribute__((guarded_by(mu_))) b, c;
|
|
|
|
private:
|
|
Mu mu_;
|
|
};
|
|
|
|
|
|
namespace NestedClassLateDecl {
|
|
|
|
class Foo {
|
|
class Bar {
|
|
int a GUARDED_BY(mu);
|
|
int b GUARDED_BY(fooMuStatic);
|
|
|
|
void bar() EXCLUSIVE_LOCKS_REQUIRED(mu) { a = 0; }
|
|
void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu) { b->a = 0; }
|
|
void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; }
|
|
|
|
Mu mu;
|
|
};
|
|
|
|
int a GUARDED_BY(fooMu);
|
|
Mu fooMu;
|
|
static Mu fooMuStatic;
|
|
};
|
|
|
|
}
|
|
|
|
} // end namespace TestMultiDecl
|
|
|