mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 00:26:06 +00:00
Thread-Safety: added support for 'this' as a lock expression.
llvm-svn: 150700
This commit is contained in:
parent
fbb50f19ad
commit
bc8ffdb68c
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user