aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2012-02-16 17:03:24 +0000
committerDeLesley Hutchins <delesley@google.com>2012-02-16 17:03:24 +0000
commit4bda3eca138d39585c9e475ad25aa9ff053f923b (patch)
tree0dfa235cf287ce7d54ff12ae48923c7ad8cceff5
parentc24a2335677f3d1bd2cab1019ac445d650f52123 (diff)
Thread-Safety: added support for 'this' as a lock expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150700 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/ThreadSafety.cpp10
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp30
2 files changed, 37 insertions, 3 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index f4386538d7..5a08ec6b21 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -62,11 +62,11 @@ namespace {
///
/// Clang introduces an additional wrinkle, which is that it is difficult to
/// derive canonical expressions, or compare expressions directly for equality.
-/// Thus, we identify a mutex not by an Expr, but by the set of named
+/// Thus, we identify a mutex not by an Expr, but by the list of named
/// declarations that are referenced by the Expr. In other words,
/// x->foo->bar.mu will be a four element vector with the Decls for
/// mu, bar, and foo, and x. The vector will uniquely identify the expression
-/// for all practical purposes.
+/// for all practical purposes. Null is used to denote 'this'.
///
/// Note we will need to perform substitution on "this" and function parameter
/// names when constructing a lock expression.
@@ -122,8 +122,10 @@ class MutexID {
} else if (isa<CXXThisExpr>(Exp)) {
if (Parent)
buildMutexID(Parent, D, 0, 0, 0);
- else
+ else {
+ DeclSeq.push_back(0); // Use 0 to represent 'this'.
return; // mutexID is still valid in this case
+ }
} else if (UnaryOperator *UOE = dyn_cast<UnaryOperator>(Exp))
buildMutexID(UOE->getSubExpr(), D, Parent, NumArgs, FunArgs);
else if (CastExpr *CE = dyn_cast<CastExpr>(Exp))
@@ -233,6 +235,8 @@ public:
/// We do not want to output the entire expression text for security reasons.
StringRef getName() const {
assert(isValid());
+ if (!DeclSeq.front())
+ return "this"; // Use 0 to represent 'this'.
return DeclSeq.front()->getName();
}
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index e0fde6b255..20d816a41d 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -2049,5 +2049,35 @@ void test() {
// expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
}
+} // end namespace FunctionDefinitionTest
+
+
+namespace SelfLockingTest {
+
+class LOCKABLE MyLock {
+public:
+ int foo GUARDED_BY(this);
+
+ void lock() EXCLUSIVE_LOCK_FUNCTION();
+ void unlock() UNLOCK_FUNCTION();
+
+ void doSomething() {
+ this->lock(); // allow 'this' as a lock expression
+ foo = 0;
+ doSomethingElse();
+ this->unlock();
+ }
+
+ void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
+ foo = 1;
+ };
+
+ void test() {
+ foo = 2; // \
+ // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
+ }
};
+} // end namespace SelfLockingTest
+
+