From bc8ffdb68ca93699080cf43f7d46a6a5cc0dba6f Mon Sep 17 00:00:00 2001 From: DeLesley Hutchins Date: Thu, 16 Feb 2012 17:03:24 +0000 Subject: [PATCH] Thread-Safety: added support for 'this' as a lock expression. llvm-svn: 150700 --- clang/lib/Analysis/ThreadSafety.cpp | 10 +++++-- .../SemaCXX/warn-thread-safety-analysis.cpp | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index f4386538d7ae..5a08ec6b21de 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/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(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(Exp)) buildMutexID(UOE->getSubExpr(), D, Parent, NumArgs, FunArgs); else if (CastExpr *CE = dyn_cast(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/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index e0fde6b2555c..20d816a41d8c 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/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 + +