From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- clang/test/SemaCXX/warn-thread-safety-parsing.cpp | 1345 +++++++++++++++++++++ 1 file changed, 1345 insertions(+) create mode 100644 clang/test/SemaCXX/warn-thread-safety-parsing.cpp (limited to 'clang/test/SemaCXX/warn-thread-safety-parsing.cpp') diff --git a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp new file mode 100644 index 0000000..c2fa1d7 --- /dev/null +++ b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -0,0 +1,1345 @@ +// 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 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 +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 + void foo6() __attribute__((exclusive_locks_required(T::statmu))) { } + + template + 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 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 +void Bar::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 + -- cgit v1.2.3