diff options
-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 + + |