blob: 5afba485014a27524e0ce32a98dd052ddc5117fd [file] [log] [blame]
// Test lock annotations
// This is a "good" test case that should not incur any thread safety warning.
// { dg-do compile }
// { dg-options "-Wthread-safety -O" }
#include "thread_annot_common.h"
Mutex mu1;
class Foo {
public:
Mutex mu_ ACQUIRED_AFTER(mu1);
static Mutex mu2_[7] ACQUIRED_AFTER(mu_);
int a_ GUARDED_BY(mu_);
float b_ GUARDED_BY(mu_);
void foo() const SHARED_LOCKS_REQUIRED(mu_);
void bar() EXCLUSIVE_LOCKS_REQUIRED((mu2_[0]));
inline Mutex *get_lock() LOCK_RETURNED(mu_) { return &mu_; }
inline Mutex *get_lock2() { return &mu_; }
static bool compare(Foo& x, Foo& y)
{
x.mu_.Lock();
y.get_lock()->Lock();
if (x.a_ > y.a_ && x.b_ > y.b_) {
y.mu_.Unlock();
x.get_lock()->Unlock();
return true;
}
else {
y.get_lock()->Unlock();
x.mu_.Unlock();
return false;
}
}
};
class Bar {
public:
Foo foo[3];
Foo *get_foo() __attribute__((pure)) { return &foo[2]; }
};
class Cat {
public:
Bar *bar;
};
Foo *q GUARDED_BY(mu1);
Foo y;
Cat w[3];
Bar *p GUARDED_BY((y.mu_));
int gx GUARDED_BY((w[1].bar->foo[2].mu_));
main()
{
Foo x;
Foo::compare(x, y);
mu1.Lock();
q->mu_.Lock();
q->mu2_[0].Lock();
q->foo();
q->a_ = 5;
q->bar();
q->mu2_[0].Unlock();
q->mu_.Unlock();
mu1.Unlock();
w[2].bar->foo[1].mu_.Lock();
w[2].bar->foo[1].a_ = 3;
Foo::mu2_[0].Lock();
w[2].bar->foo[1].bar();
Foo::mu2_[0].Unlock();
w[2].bar->foo[1].mu_.Unlock();
w[1].bar->foo[2].get_lock()->Lock();
gx = 7;
w[1].bar->foo[2].get_lock()->Unlock();
y.mu_.Lock();
p->foo[2].get_lock()->Lock();
p->foo[2].b_ += 1;
p->foo[2].mu_.Unlock();
y.a_ = 2;
y.mu_.Unlock();
}