diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-07-03 18:25:56 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-07-03 18:25:56 +0000 |
commit | 9d6e7f3e12f1a825377ace33161e80caeda8cd06 (patch) | |
tree | 2e3c2779c8a60a56df8421fd45ed0c76ff06f960 | |
parent | 57aceb227d192ce41f5412a53d451354e90dd792 (diff) |
Thread Safety Analysis: handle expressions involving temporaries,
e.g. ExprWithCleanups.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159674 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/ThreadSafety.cpp | 22 | ||||
-rw-r--r-- | test/SemaCXX/warn-thread-safety-analysis.cpp | 40 |
2 files changed, 54 insertions, 8 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index f9d93ee0df..238a888194 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -206,15 +206,17 @@ class MutexID { buildMutexID(CE->getSubExpr(), CallCtx); } else if (ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) { buildMutexID(PE->getSubExpr(), CallCtx); + } else if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Exp)) { + buildMutexID(EWC->getSubExpr(), CallCtx); } else if (isa<CharacterLiteral>(Exp) || - isa<CXXNullPtrLiteralExpr>(Exp) || - isa<GNUNullExpr>(Exp) || - isa<CXXBoolLiteralExpr>(Exp) || - isa<FloatingLiteral>(Exp) || - isa<ImaginaryLiteral>(Exp) || - isa<IntegerLiteral>(Exp) || - isa<StringLiteral>(Exp) || - isa<ObjCStringLiteral>(Exp)) { + isa<CXXNullPtrLiteralExpr>(Exp) || + isa<GNUNullExpr>(Exp) || + isa<CXXBoolLiteralExpr>(Exp) || + isa<FloatingLiteral>(Exp) || + isa<ImaginaryLiteral>(Exp) || + isa<IntegerLiteral>(Exp) || + isa<StringLiteral>(Exp) || + isa<ObjCStringLiteral>(Exp)) { return; // FIXME: Ignore literals for now } else { // Ignore. FIXME: mark as invalid expression? @@ -1523,6 +1525,10 @@ void BuildLockset::VisitDeclStmt(DeclStmt *S) { Decl *D = *I; if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) { Expr *E = VD->getInit(); + // handle constructors that involve temporaries + if (ExprWithCleanups *EWC = dyn_cast_or_null<ExprWithCleanups>(E)) + E = EWC->getSubExpr(); + if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) { NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor()); if (!CtorD || !CtorD->hasAttrs()) diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 2bf9ed4079..de3f321379 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -57,6 +57,23 @@ class SCOPED_LOCKABLE ReleasableMutexLock { void Release() UNLOCK_FUNCTION(); }; + +template<class T> +class SmartPtr { +public: + SmartPtr(T* p) : ptr_(p) { } + SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { } + ~SmartPtr(); + + T* get() const { return ptr_; } + T* operator->() const { return ptr_; } + T& operator*() const { return ptr_; } + +private: + T* ptr_; +}; + + Mutex sls_mu; Mutex sls_mu2 __attribute__((acquired_after(sls_mu))); @@ -2535,3 +2552,26 @@ class Foo { } // end namespace FoolishScopedLockableBug + +namespace TemporaryCleanupExpr { + +class Foo { + int a GUARDED_BY(getMutexPtr().get()); + + SmartPtr<Mutex> getMutexPtr(); + + void test(); +}; + + +void Foo::test() { + { + ReaderMutexLock lock(getMutexPtr().get()); + int b = a; + } // FIXME: handle smart pointers better. + int b = a; // expected-warning {{reading variable 'a' requires locking 'get'}} +} + +} // end namespace TemporaryCleanupExpr + + |