diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-06-28 22:42:48 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-06-28 22:42:48 +0000 |
commit | c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6 (patch) | |
tree | 76100c34b24528961d5d0800a3e8a2ebbfbf65c2 /lib/Analysis | |
parent | b956e5a2439bce94ba2e1da264471859632eb11f (diff) |
Thread safety analysis: support release() function on scoped
lockable objects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159387 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/ThreadSafety.cpp | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index 2668de1b05..fd4551b975 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -349,14 +349,18 @@ struct LockData { /// /// FIXME: add support for re-entrant locking and lock up/downgrading LockKind LKind; - MutexID UnderlyingMutex; // for ScopedLockable objects + bool Managed; // for ScopedLockable objects + MutexID UnderlyingMutex; // for ScopedLockable objects - LockData(SourceLocation AcquireLoc, LockKind LKind) - : AcquireLoc(AcquireLoc), LKind(LKind), UnderlyingMutex(Decl::EmptyShell()) + LockData(SourceLocation AcquireLoc, LockKind LKind, bool M = false) + : AcquireLoc(AcquireLoc), LKind(LKind), Managed(M), + UnderlyingMutex(Decl::EmptyShell()) {} LockData(SourceLocation AcquireLoc, LockKind LKind, const MutexID &Mu) - : AcquireLoc(AcquireLoc), LKind(LKind), UnderlyingMutex(Mu) {} + : AcquireLoc(AcquireLoc), LKind(LKind), Managed(false), + UnderlyingMutex(Mu) + {} bool operator==(const LockData &other) const { return AcquireLoc == other.AcquireLoc && LKind == other.LKind; @@ -924,7 +928,8 @@ public: Lockset addLock(const Lockset &LSet, Expr *MutexExp, const NamedDecl *D, const LockData &LDat); Lockset removeLock(const Lockset &LSet, const MutexID &Mutex, - SourceLocation UnlockLoc); + SourceLocation UnlockLoc, + bool Warn=true, bool FullyRemove=false); template <class AttrType> Lockset addLocksToSet(const Lockset &LSet, LockKind LK, AttrType *Attr, @@ -986,21 +991,31 @@ Lockset ThreadSafetyAnalyzer::addLock(const Lockset &LSet, /// \param UnlockLoc The source location of the unlock (only used in error msg) Lockset ThreadSafetyAnalyzer::removeLock(const Lockset &LSet, const MutexID &Mutex, - SourceLocation UnlockLoc) { + SourceLocation UnlockLoc, + bool Warn, bool FullyRemove) { const LockData *LDat = LSet.lookup(Mutex); if (!LDat) { - Handler.handleUnmatchedUnlock(Mutex.getName(), UnlockLoc); + if (Warn) + Handler.handleUnmatchedUnlock(Mutex.getName(), UnlockLoc); return LSet; } else { Lockset Result = LSet; - // For scoped-lockable vars, remove the mutex associated with this var. - if (LDat->UnderlyingMutex.isValid()) - Result = removeLock(Result, LDat->UnderlyingMutex, UnlockLoc); + if (LDat->UnderlyingMutex.isValid()) { + // For scoped-lockable vars, remove the mutex associated with this var. + Result = removeLock(Result, LDat->UnderlyingMutex, UnlockLoc, + false, true); + // Fully remove the object only when the destructor is called + if (FullyRemove) + return LocksetFactory.remove(Result, Mutex); + else + return Result; + } return LocksetFactory.remove(Result, Mutex); } } + /// \brief This function, parameterized by an attribute type, is used to add a /// set of locks specified as attribute arguments to the lockset. template <typename AttrType> @@ -1040,14 +1055,18 @@ Lockset ThreadSafetyAnalyzer::addLocksToSet(const Lockset &LSet, if (!Mutex.isValid()) MutexID::warnInvalidLock(Handler, *I, Exp, FunDecl); else { - Result = addLock(Result, Mutex, LockData(ExpLocation, LK)); if (isScopedVar) { + // Mutex is managed by scoped var -- suppress certain warnings. + Result = addLock(Result, Mutex, LockData(ExpLocation, LK, true)); // For scoped lockable vars, map this var to its underlying mutex. DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation()); MutexID SMutex(&DRE, 0, 0); Result = addLock(Result, SMutex, LockData(VD->getLocation(), LK, Mutex)); } + else { + Result = addLock(Result, Mutex, LockData(ExpLocation, LK)); + } } } return Result; @@ -1057,9 +1076,11 @@ Lockset ThreadSafetyAnalyzer::addLocksToSet(const Lockset &LSet, /// arguments from the lockset. Lockset ThreadSafetyAnalyzer::removeLocksFromSet(const Lockset &LSet, UnlockFunctionAttr *Attr, - Expr *Exp, NamedDecl* FunDecl) { + Expr *Exp, + NamedDecl* FunDecl) { SourceLocation ExpLocation; if (Exp) ExpLocation = Exp->getExprLoc(); + bool Dtor = isa<CXXDestructorDecl>(FunDecl); if (Attr->args_size() == 0) { // The mutex held is the "this" object. @@ -1068,7 +1089,7 @@ Lockset ThreadSafetyAnalyzer::removeLocksFromSet(const Lockset &LSet, MutexID::warnInvalidLock(Handler, 0, Exp, FunDecl); return LSet; } else { - return removeLock(LSet, Mu, ExpLocation); + return removeLock(LSet, Mu, ExpLocation, true, Dtor); } } @@ -1079,7 +1100,7 @@ Lockset ThreadSafetyAnalyzer::removeLocksFromSet(const Lockset &LSet, if (!Mutex.isValid()) MutexID::warnInvalidLock(Handler, *I, Exp, FunDecl); else - Result = removeLock(Result, Mutex, ExpLocation); + Result = removeLock(Result, Mutex, ExpLocation, true, Dtor); } return Result; } @@ -1537,9 +1558,10 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1, LSet2LockData); } } else { - Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(), - LSet2LockData.AcquireLoc, - JoinLoc, LEK); + if (!LSet2LockData.Managed) + Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(), + LSet2LockData.AcquireLoc, + JoinLoc, LEK); } } @@ -1547,9 +1569,11 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1, if (!LSet2.contains(I.getKey())) { const MutexID &Mutex = I.getKey(); const LockData &MissingLock = I.getData(); - Handler.handleMutexHeldEndOfScope(Mutex.getName(), - MissingLock.AcquireLoc, - JoinLoc, LEK); + + if (!MissingLock.Managed) + Handler.handleMutexHeldEndOfScope(Mutex.getName(), + MissingLock.AcquireLoc, + JoinLoc, LEK); Intersection = LocksetFactory.remove(Intersection, Mutex); } } |