diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-10-12 21:38:12 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-10-12 21:38:12 +0000 |
commit | 3ce9fae275ec05cd648d6093b95eb1d05bc14a98 (patch) | |
tree | 2e910de43c81f6bccc12c482c4f999f1328e1ce4 | |
parent | fba3fb9a14f2d729639e0fdb834e3eeb40a8a12a (diff) |
Thread-safety analysis: support multiple thread-safety attributes on
declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165826 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 17 | ||||
-rw-r--r-- | test/SemaCXX/warn-thread-safety-analysis.cpp | 91 |
2 files changed, 108 insertions, 0 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ee246b81a6..a00f60f681 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1724,6 +1724,23 @@ DeclHasAttr(const Decl *D, const Attr *A) { if (AA) return false; + // The following thread safety attributes can also be duplicated. + switch (A->getKind()) { + case attr::ExclusiveLocksRequired: + case attr::SharedLocksRequired: + case attr::LocksExcluded: + case attr::ExclusiveLockFunction: + case attr::SharedLockFunction: + case attr::UnlockFunction: + case attr::ExclusiveTrylockFunction: + case attr::SharedTrylockFunction: + case attr::GuardedBy: + case attr::PtGuardedBy: + case attr::AcquiredBefore: + case attr::AcquiredAfter: + return false; + } + const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A); const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A); for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 92d88c0970..bd555ac56c 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -3621,3 +3621,94 @@ void test2() { } // end namespace SelfConstructorTest + +namespace MultipleAttributeTest { + +class Foo { + Mutex mu1_; + Mutex mu2_; + int a GUARDED_BY(mu1_); + int b GUARDED_BY(mu2_); + int c GUARDED_BY(mu1_) GUARDED_BY(mu2_); + int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_); + + void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_) + EXCLUSIVE_LOCKS_REQUIRED(mu2_); + void foo2() SHARED_LOCKS_REQUIRED(mu1_) + SHARED_LOCKS_REQUIRED(mu2_); + void foo3() LOCKS_EXCLUDED(mu1_) + LOCKS_EXCLUDED(mu2_); + void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_) + EXCLUSIVE_LOCK_FUNCTION(mu2_); + void readerlock() EXCLUSIVE_LOCK_FUNCTION(mu1_) + EXCLUSIVE_LOCK_FUNCTION(mu2_); + void unlock() UNLOCK_FUNCTION(mu1_) + UNLOCK_FUNCTION(mu2_); + bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_) + EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_); + bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_) + SHARED_TRYLOCK_FUNCTION(true, mu2_); + + void test(); +}; + + +void Foo::foo1() { + a = 1; + b = 2; +} + +void Foo::foo2() { + int result = a + b; +} + +void Foo::foo3() { } +void Foo::lock() { } +void Foo::readerlock() { } +void Foo::unlock() { } +bool Foo::trylock() { return true; } +bool Foo::readertrylock() { return true; } + + +void Foo::test() { + mu1_.Lock(); + foo1(); // expected-warning {{}} + c = 0; // expected-warning {{}} + *d = 0; // expected-warning {{}} + mu1_.Unlock(); + + mu1_.ReaderLock(); + foo2(); // expected-warning {{}} + int x = c; // expected-warning {{}} + int y = *d; // expected-warning {{}} + mu1_.Unlock(); + + mu2_.Lock(); + foo3(); // expected-warning {{}} + mu2_.Unlock(); + + lock(); + a = 0; + b = 0; + unlock(); + + readerlock(); + int z = a + b; + unlock(); + + if (trylock()) { + a = 0; + b = 0; + unlock(); + } + + if (readertrylock()) { + int zz = a + b; + unlock(); + } +} + + +} // end namespace MultipleAttributeTest + + |