From 9d6e7f3e12f1a825377ace33161e80caeda8cd06 Mon Sep 17 00:00:00 2001 From: DeLesley Hutchins Date: Tue, 3 Jul 2012 18:25:56 +0000 Subject: [PATCH] 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 --- lib/Analysis/ThreadSafety.cpp | 22 +++++++---- 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(Exp)) { buildMutexID(PE->getSubExpr(), CallCtx); + } else if (ExprWithCleanups *EWC = dyn_cast(Exp)) { + buildMutexID(EWC->getSubExpr(), CallCtx); } else if (isa(Exp) || - isa(Exp) || - isa(Exp) || - isa(Exp) || - isa(Exp) || - isa(Exp) || - isa(Exp) || - isa(Exp) || - isa(Exp)) { + isa(Exp) || + isa(Exp) || + isa(Exp) || + isa(Exp) || + isa(Exp) || + isa(Exp) || + isa(Exp) || + isa(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(D)) { Expr *E = VD->getInit(); + // handle constructors that involve temporaries + if (ExprWithCleanups *EWC = dyn_cast_or_null(E)) + E = EWC->getSubExpr(); + if (CXXConstructExpr *CE = dyn_cast_or_null(E)) { NamedDecl *CtorD = dyn_cast_or_null(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 SmartPtr { +public: + SmartPtr(T* p) : ptr_(p) { } + SmartPtr(const SmartPtr& 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 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 + + -- 2.40.0