[cfe-commits] r159679 - in /cfe/trunk: lib/Analysis/ThreadSafety.cpp test/SemaCXX/warn-thread-safety-analysis.cpp
DeLesley Hutchins
delesley at google.com
Tue Jul 3 12:47:19 PDT 2012
Author: delesley
Date: Tue Jul 3 14:47:18 2012
New Revision: 159679
URL: http://llvm.org/viewvc/llvm-project?rev=159679&view=rev
Log:
Thread safety analysis: improve handling of smart pointers.
Modified:
cfe/trunk/lib/Analysis/ThreadSafety.cpp
cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=159679&r1=159678&r2=159679&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Tue Jul 3 14:47:18 2012
@@ -26,6 +26,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
@@ -162,6 +163,13 @@
buildMutexID(At->getArg(), &LRCallCtx);
return;
}
+ // Hack to treat smart pointers and iterators as pointers;
+ // ignore any method named get().
+ if (CMCE->getMethodDecl()->getNameAsString() == "get" &&
+ CMCE->getNumArgs() == 0) {
+ buildMutexID(CMCE->getImplicitObjectArgument(), CallCtx);
+ return;
+ }
DeclSeq.push_back(CMCE->getMethodDecl()->getCanonicalDecl());
buildMutexID(CMCE->getImplicitObjectArgument(), CallCtx);
unsigned NumCallArgs = CMCE->getNumArgs();
@@ -179,6 +187,15 @@
buildMutexID(At->getArg(), &LRCallCtx);
return;
}
+ // Treat smart pointers and iterators as pointers;
+ // ignore the * and -> operators.
+ if (CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(CE)) {
+ OverloadedOperatorKind k = OE->getOperator();
+ if (k == OO_Arrow || k == OO_Star) {
+ buildMutexID(OE->getArg(0), CallCtx);
+ return;
+ }
+ }
buildMutexID(CE->getCallee(), CallCtx);
unsigned NumCallArgs = CE->getNumArgs();
Expr** CallArgs = CE->getArgs();
@@ -208,6 +225,8 @@
buildMutexID(PE->getSubExpr(), CallCtx);
} else if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Exp)) {
buildMutexID(EWC->getSubExpr(), CallCtx);
+ } else if (CXXBindTemporaryExpr *E = dyn_cast<CXXBindTemporaryExpr>(Exp)) {
+ buildMutexID(E->getSubExpr(), CallCtx);
} else if (isa<CharacterLiteral>(Exp) ||
isa<CXXNullPtrLiteralExpr>(Exp) ||
isa<GNUNullExpr>(Exp) ||
Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=159679&r1=159678&r2=159679&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Tue Jul 3 14:47:18 2012
@@ -67,7 +67,7 @@
T* get() const { return ptr_; }
T* operator->() const { return ptr_; }
- T& operator*() const { return ptr_; }
+ T& operator*() const { return *ptr_; }
private:
T* ptr_;
@@ -2568,10 +2568,175 @@
{
ReaderMutexLock lock(getMutexPtr().get());
int b = a;
- } // FIXME: handle smart pointers better.
- int b = a; // expected-warning {{reading variable 'a' requires locking 'get'}}
+ }
+ int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr'}}
}
} // end namespace TemporaryCleanupExpr
+
+namespace SmartPointerTests {
+
+class Foo {
+public:
+ SmartPtr<Mutex> mu_;
+ int a GUARDED_BY(mu_);
+ int b GUARDED_BY(mu_.get());
+ int c GUARDED_BY(*mu_);
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
+ void Unlock() UNLOCK_FUNCTION(mu_);
+
+ void test0();
+ void test1();
+ void test2();
+ void test3();
+ void test4();
+ void test5();
+ void test6();
+ void test7();
+ void test8();
+};
+
+void Foo::test0() {
+ a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
+ c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
+}
+
+void Foo::test1() {
+ mu_->Lock();
+ a = 0;
+ b = 0;
+ c = 0;
+ mu_->Unlock();
+}
+
+void Foo::test2() {
+ (*mu_).Lock();
+ a = 0;
+ b = 0;
+ c = 0;
+ (*mu_).Unlock();
+}
+
+
+void Foo::test3() {
+ mu_.get()->Lock();
+ a = 0;
+ b = 0;
+ c = 0;
+ mu_.get()->Unlock();
+}
+
+
+void Foo::test4() {
+ MutexLock lock(mu_.get());
+ a = 0;
+ b = 0;
+ c = 0;
+}
+
+
+void Foo::test5() {
+ MutexLock lock(&(*mu_));
+ a = 0;
+ b = 0;
+ c = 0;
+}
+
+
+void Foo::test6() {
+ Lock();
+ a = 0;
+ b = 0;
+ c = 0;
+ Unlock();
+}
+
+
+void Foo::test7() {
+ {
+ Lock();
+ mu_->Unlock();
+ }
+ {
+ mu_->Lock();
+ Unlock();
+ }
+ {
+ mu_.get()->Lock();
+ mu_->Unlock();
+ }
+ {
+ mu_->Lock();
+ mu_.get()->Unlock();
+ }
+ {
+ mu_.get()->Lock();
+ (*mu_).Unlock();
+ }
+ {
+ (*mu_).Lock();
+ mu_->Unlock();
+ }
+}
+
+
+void Foo::test8() {
+ mu_->Lock();
+ mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
+ (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
+ mu_.get()->Unlock();
+ Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
+}
+
+
+class Bar {
+ SmartPtr<Foo> foo;
+
+ void test0();
+ void test1();
+ void test2();
+ void test3();
+};
+
+
+void Bar::test0() {
+ foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
+ foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
+}
+
+
+void Bar::test1() {
+ foo->mu_->Lock();
+ foo->a = 0;
+ (*foo).b = 0;
+ foo.get()->c = 0;
+ foo->mu_->Unlock();
+}
+
+
+void Bar::test2() {
+ (*foo).mu_->Lock();
+ foo->a = 0;
+ (*foo).b = 0;
+ foo.get()->c = 0;
+ foo.get()->mu_->Unlock();
+}
+
+
+void Bar::test3() {
+ MutexLock lock(foo->mu_.get());
+ foo->a = 0;
+ (*foo).b = 0;
+ foo.get()->c = 0;
+}
+
+} // end namespace SmartPointerTests
+
+
+
+
More information about the cfe-commits
mailing list