diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-09-10 19:58:23 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-09-10 19:58:23 +0000 |
commit | 3f0ec5209726641782468bd4c7597e79dda78b15 (patch) | |
tree | dea619fabad3cecc1516644084b6ac886a32a8b7 /lib/Analysis/ThreadSafety.cpp | |
parent | bd7e30605253ae053087619173713c19355e28ea (diff) |
Thread-safety analysis: differentiate between two forms of analysis; a precise
analysis that may give false positives because it is confused by aliasing, and
a less precise analysis that has fewer false positives, but may have false
negatives. The more precise warnings are enabled by -Wthread-safety-precise.
An additional note clarify the warnings in the precise case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163537 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ThreadSafety.cpp')
-rw-r--r-- | lib/Analysis/ThreadSafety.cpp | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index 9c5fb1a145..8875943480 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -575,6 +575,15 @@ public: return false; } + // A partial match between a.mu and b.mu returns true a and b have the same + // type (and thus mu refers to the same mutex declaration), regardless of + // whether a and b are different objects or not. + bool partiallyMatches(const SExpr &Other) const { + if (NodeVec[0].kind() == EOP_Dot) + return NodeVec[0].matches(Other.NodeVec[0]); + return false; + } + /// \brief Pretty print a lock expression for use in error messages. std::string toString(unsigned i = 0) const { assert(isValid()); @@ -820,7 +829,7 @@ public: return false; } - LockData* findLock(FactManager& FM, const SExpr& M) const { + LockData* findLock(FactManager &FM, const SExpr &M) const { for (const_iterator I = begin(), E = end(); I != E; ++I) { const SExpr &Exp = FM[*I].MutID; if (Exp.matches(M)) @@ -829,7 +838,7 @@ public: return 0; } - LockData* findLockUniv(FactManager& FM, const SExpr& M) const { + LockData* findLockUniv(FactManager &FM, const SExpr &M) const { for (const_iterator I = begin(), E = end(); I != E; ++I) { const SExpr &Exp = FM[*I].MutID; if (Exp.matches(M) || Exp.isUniversal()) @@ -837,6 +846,14 @@ public: } return 0; } + + FactEntry* findPartialMatch(FactManager &FM, const SExpr &M) const { + for (const_iterator I=begin(), E=end(); I != E; ++I) { + const SExpr& Exp = FM[*I].MutID; + if (Exp.partiallyMatches(M)) return &FM[*I]; + } + return 0; + } }; @@ -1742,7 +1759,26 @@ void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, Expr *Exp, } LockData* LDat = FSet.findLockUniv(Analyzer->FactMan, Mutex); - if (!LDat || !LDat->isAtLeast(LK)) + bool NoError = true; + if (!LDat) { + // No exact match found. Look for a partial match. + FactEntry* FEntry = FSet.findPartialMatch(Analyzer->FactMan, Mutex); + if (FEntry) { + // Warn that there's no precise match. + LDat = &FEntry->LDat; + std::string PartMatchStr = FEntry->MutID.toString(); + StringRef PartMatchName(PartMatchStr); + Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK, + Exp->getExprLoc(), &PartMatchName); + } else { + // Warn that there's no match at all. + Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK, + Exp->getExprLoc()); + } + NoError = false; + } + // Make sure the mutex we found is the right kind. + if (NoError && LDat && !LDat->isAtLeast(LK)) Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK, Exp->getExprLoc()); } |