diff options
Diffstat (limited to 'gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann')
20 files changed, 659 insertions, 0 deletions
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h index 192c84e84..a21af97fe 100644 --- a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h @@ -27,6 +27,11 @@ #define SHARED_LOCKS_REQUIRED(...) \ __attribute__ ((shared_locks_required(__VA_ARGS__))) #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) +#define IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin)) +#define IGNORE_READS_END __attribute__ ((ignore_reads_end)) +#define IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin)) +#define IGNORE_WRITES_END __attribute__ ((ignore_writes_end)) +#define UNPROTECTED_READ __attribute__ ((unprotected_read)) #else @@ -48,6 +53,11 @@ #define EXCLUSIVE_LOCKS_REQUIRED(...) #define SHARED_LOCKS_REQUIRED(...) #define NO_THREAD_SAFETY_ANALYSIS +#define IGNORE_READS_BEGIN +#define IGNORE_READS_END +#define IGNORE_WRITES_BEGIN +#define IGNORE_WRITES_END +#define UNPROTECTED_READ #endif // defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__) @@ -81,4 +91,41 @@ class SCOPED_LOCKABLE ReleasableMutexLock { void Release() UNLOCK_FUNCTION(); }; +void AnnotateIgnoreReadsBegin(const char *file, int line) IGNORE_READS_BEGIN; +void AnnotateIgnoreReadsEnd(const char *file, int line) IGNORE_READS_END; +void AnnotateIgnoreWritesBegin(const char *file, int line) IGNORE_WRITES_BEGIN; +void AnnotateIgnoreWritesEnd(const char *file, int line) IGNORE_WRITES_END; + +#define ANNOTATE_IGNORE_READS_BEGIN() \ + AnnotateIgnoreReadsBegin(__FILE__, __LINE__) + +#define ANNOTATE_IGNORE_READS_END() \ + AnnotateIgnoreReadsEnd(__FILE__, __LINE__) + +#define ANNOTATE_IGNORE_WRITES_BEGIN() \ + AnnotateIgnoreWritesBegin(__FILE__, __LINE__) + +#define ANNOTATE_IGNORE_WRITES_END() \ + AnnotateIgnoreWritesEnd(__FILE__, __LINE__) + +#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \ + do { \ + ANNOTATE_IGNORE_READS_BEGIN(); \ + ANNOTATE_IGNORE_WRITES_BEGIN(); \ + }while(0) \ + +#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \ + do { \ + ANNOTATE_IGNORE_WRITES_END(); \ + ANNOTATE_IGNORE_READS_END(); \ + }while(0) \ + +template <class T> +inline T ANNOTATE_UNPROTECTED_READ(const T &x) UNPROTECTED_READ { + ANNOTATE_IGNORE_READS_BEGIN(); + T res = x; + ANNOTATE_IGNORE_READS_END(); + return res; +} + #endif // THREAD_ANNOT_COMMON_H diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C new file mode 100644 index 000000000..e1e24c18e --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C @@ -0,0 +1,22 @@ +// Test the support for allowing non-const but non-modifying methods to be +// protected by reader locks. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include <map> +#include "thread_annot_common.h" + +typedef std::map<int, int> MyMapType; + +Mutex mu; +MyMapType MyMap GUARDED_BY(mu); + +int foo(int key) { + ReaderMutexLock l(&mu); + MyMapType::const_iterator iter = MyMap.find(key); + if (iter != MyMap.end()) { + return iter->second; + } +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C new file mode 100644 index 000000000..400c81e82 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C @@ -0,0 +1,44 @@ +// Test the support for allowing non-const but non-modifying methods to be +// protected by reader locks. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +class Foo { + public: + int GetVal1(int a) const { + return a + val1; + } + + int GetVal1(int a) { + return a + val1; + } + + int GetVal1(int a, float b) { + return a + b + val1; + } + + int GetVal2(int a) { + return a + val2; + } + + int GetVal2(float a) { + return val2; + } + + + private: + int val1; + int val2; +}; + +Mutex mu; +Foo foo GUARDED_BY(mu); + +int main() { + mu.ReaderLock(); + int x = foo.GetVal1(3); // should not warn + int y = foo.GetVal2(3); // { dg-warning "Writing to variable" } + mu.Unlock(); +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C new file mode 100644 index 000000000..5535034b0 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C @@ -0,0 +1,39 @@ +// Test the support for use of point_to_guarded{_by} on smart/scoped pointers. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +template<class T> +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T * p = 0); + ~scoped_ptr(); + + void reset(T * p = 0); + + T & operator*() const; + T * operator->() const; + T * get() const; +}; + +class Foo { + public: + int x; +}; + +Mutex mu1, mu2; +scoped_ptr<int> a PT_GUARDED_BY(mu1); +scoped_ptr<Foo> b GUARDED_BY(mu2) PT_GUARDED_VAR; + +main() +{ + *a = 5; // { dg-warning "Access to memory location pointed to" } + a.reset(); + b->x = 3 + *a; // { dg-warning "Reading variable" } +} + +// { dg-warning "Access to memory location pointed to by variable 'b'" "" { target *-*-* } 35 } +// { dg-warning "Access to memory location pointed to by variable 'a'" "" { target *-*-* } 35 } diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C new file mode 100644 index 000000000..0c03d77d9 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C @@ -0,0 +1,40 @@ +// Test the support for use of point_to_guarded{_by} on smart/scoped pointers. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +template<class T> +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T * p = 0); + ~scoped_ptr(); + + void reset(T * p = 0); + + T & operator*() const; + T * operator->() const; + T * get() const; +}; + +class Foo { + public: + int x; +}; + +Mutex mu1, mu2; +scoped_ptr<int> a PT_GUARDED_BY(mu1); +scoped_ptr<Foo> b GUARDED_BY(mu2) PT_GUARDED_VAR; + +main() +{ + MutexLock l1(&mu1); + MutexLock l2(&mu2); + *a = 5; + a.reset(); + b->x = 3 + *a; +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C new file mode 100644 index 000000000..e90652407 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C @@ -0,0 +1,35 @@ +// Test the handling of the annotations with function parameters. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +class Base { + private: + Mutex mu1_; + + public: + Mutex *mutable_mu() LOCK_RETURNED(mu1_) { return &mu1_; } +}; + +class Foo { + public: + Mutex mu2_; + void Test1(Mutex* mu) const EXCLUSIVE_LOCKS_REQUIRED(mu, mu2_); + void Test2(Mutex* mu) const LOCKS_EXCLUDED(mu); +}; + +class Bar : public Base { + private: + Foo foo_; + + public: + void Test3(); +}; + +void Bar::Test3() { + mutable_mu()->Lock(); + foo_.Test1(mutable_mu()); // { dg-warning "Calling function" } + foo_.Test2(mutable_mu()); // { dg-warning "Cannot call function" } + mutable_mu()->Unlock(); +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C new file mode 100644 index 000000000..10a12d43e --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C @@ -0,0 +1,38 @@ +// Test the handling of the annotations with function parameters. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +class Base { + private: + Mutex mu1_; + + public: + Mutex *mutable_mu() LOCK_RETURNED(mu1_) { return &mu1_; } +}; + +class Foo { + public: + Mutex mu2_; + void Test1(Mutex* mu) const EXCLUSIVE_LOCKS_REQUIRED(mu, mu2_); + void Test2(Mutex* mu) const LOCKS_EXCLUDED(mu); +}; + +class Bar : public Base { + private: + Foo foo_; + + public: + void Test3(); +}; + +void Bar::Test3() { + MutexLock l(&foo_.mu2_); + mutable_mu()->Lock(); + foo_.Test1(mutable_mu()); + mutable_mu()->Unlock(); + foo_.Test2(mutable_mu()); +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C new file mode 100644 index 000000000..71221eb5f --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C @@ -0,0 +1,36 @@ +// Test the handling of a method with lock annotations accessed through a +// smart/scoped pointer. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +template<class T> +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T * p = 0); + ~scoped_ptr(); + + void reset(T * p = 0); + + T & operator*() const; + T * operator->() const; + T * get() const; +}; + +class LOCKABLE Foo { + public: + Mutex *mutex_; + int x; + int GetValue() EXCLUSIVE_LOCKS_REQUIRED(mutex); +}; + +scoped_ptr<Foo> b; + +main() +{ + int a; + a = b->GetValue(); // { dg-warning "Calling function 'GetValue' requires" } +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C new file mode 100644 index 000000000..a12150436 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C @@ -0,0 +1,22 @@ +// Test handling of arguments passed to reference parameters. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +struct Foo { + int a; +}; + +void func1(Foo &f); + +void func2(Foo *f); + +Mutex mu; + +Foo foo GUARDED_BY(mu); + +main() { + func1(foo); // { dg-warning "Reading variable 'foo' requires lock" } + func2(&foo); // should not warn +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C new file mode 100644 index 000000000..858e63558 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C @@ -0,0 +1,32 @@ +// Test handling of arguments passed to reference parameters. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include <string> +#include "thread_annot_common.h" + +class Base { + public: + Base() {} + protected: + Mutex* mutex() const LOCK_RETURNED(mutex_) { return &mutex_; } + private: + mutable Mutex mutex_; +}; + +class Subclass : public Base { + public: + Subclass() {} + + void ClearValue() { SetValueLocked(0); } + std::string GetValue() const; + + private: + void SetValueLocked(std::string value) { value_ = value; } + + std::string value_ GUARDED_BY(mutex_); +}; + +std::string Subclass::GetValue() const { + return value_; // { dg-warning "Reading variable 'value_' requires lock" } +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C new file mode 100644 index 000000000..158c940e2 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C @@ -0,0 +1,34 @@ +// Test handling of additional (finer-grained) escape hatche attributes. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +Mutex *mu1, *mu2; + +struct Foo { + int a GUARDED_BY(mu1); +}; + +int x GUARDED_BY(mu1) = 1; +int y GUARDED_BY(mu2); + +main() { + int z; + Foo w; + ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); + y = x + 1; + x = y; + ANNOTATE_IGNORE_READS_AND_WRITES_END(); + + z = ANNOTATE_UNPROTECTED_READ(w.a) + 1; + if (z > 1) { + ANNOTATE_IGNORE_READS_BEGIN(); + z = x + 2; + } + else { + ANNOTATE_IGNORE_READS_BEGIN(); + z = x + 1; + } + z = y; +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C new file mode 100644 index 000000000..099aa8290 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C @@ -0,0 +1,37 @@ +// Test handling of additional (finer-grained) escape hatche attributes. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +Mutex *mu1, *mu2; + +struct Foo { + int a GUARDED_BY(mu1); +}; + +int x GUARDED_BY(mu1) = 1; +int y GUARDED_BY(mu2); + +main() { + int z; + Foo w; + ANNOTATE_IGNORE_READS_BEGIN(); + y = x + 1; // { dg-warning "Writing to variable 'y' requires lock" } + x = y; // { dg-warning "Writing to variable 'x' requires lock" } + ANNOTATE_IGNORE_READS_END(); + ANNOTATE_IGNORE_WRITES_BEGIN(); + y = x + 1; // { dg-warning "Reading variable 'x' requires lock" } + x = y; // { dg-warning "Reading variable 'y' requires lock" } + ANNOTATE_IGNORE_WRITES_END(); + + z = w.a + 1; // { dg-warning "Reading variable 'w.a' requires lock" } + if (z > 1) { + z = x + 2; // { dg-warning "Reading variable 'x' requires lock" } + } + else { + ANNOTATE_IGNORE_READS_BEGIN(); + z = x + 1; + } + z = y; // { dg-warning "Reading variable 'y' requires lock" } +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C new file mode 100644 index 000000000..11f6308eb --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C @@ -0,0 +1,15 @@ +// Test the fix for a bug introduced by the support of pass-by-reference +// paramters. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +struct Foo { Foo & operator<< (bool) {} }; +struct Bar { Foo & func () {} }; +struct Bas { void operator& (Foo &) {} }; +void mumble() +{ + Bas() & Bar().func() << "" << ""; + Bas() & Bar().func() << ""; +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C new file mode 100644 index 000000000..95f318699 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C @@ -0,0 +1,18 @@ +// Test the support for allowing non-const but non-modifying overloaded +// operator to be protected by reader locks. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include <vector> +#include "thread_annot_common.h" + +Mutex mu; + +std::vector<int> counts GUARDED_BY(mu); + +int foo(int key) { + ReaderMutexLock l(&mu); + return counts[key]; +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C new file mode 100644 index 000000000..d129fc94c --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C @@ -0,0 +1,30 @@ +// Test the fix for a bug in the support of allowing reader locks for +// non-const, non-modifying overload functions. (We didn't handle the builtin +// properly.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +enum MyFlags { + Zero, + One, + Two, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine +}; + +inline MyFlags +operator|(MyFlags a, MyFlags b) +{ + return MyFlags(static_cast<int>(a) | static_cast<int>(b)); +} + +inline MyFlags& +operator|=(MyFlags& a, MyFlags b) +{ + return a = a | b; +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C new file mode 100644 index 000000000..c341973e7 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C @@ -0,0 +1,35 @@ +// Test annotations on out-of-line definitions of member functions where the +// annotations refer to locks that are also data members in the class. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +Mutex mu; + +class Foo { + public: + int method1(int i); + int data GUARDED_BY(mu1); + Mutex *mu1; + Mutex *mu2; +}; + +int Foo::method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2) +{ + return data + i; +} + +main() +{ + Foo a; + + MutexLock l(a.mu2); + a.mu1->Lock(); + mu.Lock(); + a.method1(1); + mu.Unlock(); + a.mu1->Unlock(); +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C new file mode 100644 index 000000000..be228ec20 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C @@ -0,0 +1,32 @@ +// Test annotations on out-of-line definitions of member functions where the +// annotations refer to locks that are also data members in the class. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +Mutex mu; + +class Foo { + public: + int method1(int i); + int data GUARDED_BY(mu1); + Mutex *mu1; + Mutex *mu2; +}; + +int Foo::method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3) +{ + return data + i; +} + +main() +{ + Foo a; + + a.method1(1); // { dg-warning "Calling function 'method1' requires lock" } +} + +// { dg-warning "Calling function 'method1' requires lock 'mu'" { target *-*-* } 27 } +// { dg-warning "Calling function 'method1' requires lock 'a.mu2'" { target *-*-* } 27 } +// { dg-warning "Calling function 'method1' requires lock 'mu3'" { target *-*-* } 27 } diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C new file mode 100644 index 000000000..95e8d6908 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C @@ -0,0 +1,34 @@ +// Test a fix to a bug in the delayed name binding with nested template +// instantiation. We use a stack to make sure a name is not resolved to an +// inner context. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +template <typename T> +class Bar { + Mutex mu_; +}; + +template <typename T> +class Foo { + public: + void func(T x) { + MutexLock l(&mu_); + count_ = x; + } + + private: + T count_ GUARDED_BY(mu_); + Bar<T> bar_; + Mutex mu_; +}; + +int main() +{ + Foo<int> *foo; + foo->func(5); +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C new file mode 100644 index 000000000..478e8b273 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C @@ -0,0 +1,31 @@ +// Test a fix to a bug in the delayed name binding with nested template +// instantiation. We use a stack to make sure a name is not resolved to an +// inner context. +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +template <typename T> +class Bar { + Mutex mu_; +}; + +template <typename T> +class Foo { + public: + void func(T x) { + count_ = x; // { dg-warning "Writing to variable 'count_' requires lock" } + } + + private: + T count_ GUARDED_BY(mu_); + Bar<T> bar_; + Mutex mu_; +}; + +int main() +{ + Foo<int> *foo; + foo->func(5); +} diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C new file mode 100644 index 000000000..782d13af4 --- /dev/null +++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C @@ -0,0 +1,38 @@ +// Test a fix to a bug when handling calls to virtual functions that are +// annotated with LOCK/UNLOCK_FUNCTION. More specifically, the bug happens +// when we tried to assert the function decl of a gimple call statement +// returned by gimple_call_fndecl is non-NULL, which is not true when the call +// is a virtual function call. Instead, we should either get the function decl +// through the reference object, or (as is the fix) simply pass the function +// decl that we have extracted earlier all the way to +// handle_lock_primitive_attrs where the assertion fails. +// +// This is a good test case. (i.e. There should be no error/warning/ICE +// triggered.) +// +// { dg-do compile } +// { dg-options "-Wthread-safety -O" } + +#include "thread_annot_common.h" + +class Base { + protected: + virtual void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_) { mu_.Lock(); } + virtual void Unlock() UNLOCK_FUNCTION(mu_) { mu_.Unlock(); } + Mutex mu_; +}; + +class Child: public Base { + int a; + public: + void func1() { + Lock(); + a += 1; + Unlock(); + } +}; + +main() { + Child c; + c.func1(); +} |