diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-09-26 11:33:13 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-13 20:49:29 +0000 |
commit | 28a41182c08e79534be77131840bcfdf73d31343 (patch) | |
tree | 8a1fb5602dbadb061e195f566952ce7f59ce5682 /contrib/llvm-project/clang/lib/Analysis | |
parent | 8c6f6c0c80f896f9c90b7833def615dcb0ce9244 (diff) | |
parent | 3f25e997d96a3150a192777c3c389c258c5cf7ee (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Analysis')
-rw-r--r-- | contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp index 5b2c882c4235..41a55f9579bd 100644 --- a/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp @@ -1050,7 +1050,7 @@ public: const CFGBlock* PredBlock, const CFGBlock *CurrBlock); - bool join(const FactEntry &a, const FactEntry &b); + bool join(const FactEntry &a, const FactEntry &b, bool CanModify); void intersectAndWarn(FactSet &EntrySet, const FactSet &ExitSet, SourceLocation JoinLoc, LockErrorKind EntryLEK, @@ -2188,25 +2188,28 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) { } } -/// Given two facts merging on a join point, decide whether to warn and which -/// one to keep. +/// Given two facts merging on a join point, possibly warn and decide whether to +/// keep or replace. /// -/// \return false if we should keep \p A, true if we should keep \p B. -bool ThreadSafetyAnalyzer::join(const FactEntry &A, const FactEntry &B) { +/// \param CanModify Whether we can replace \p A by \p B. +/// \return false if we should keep \p A, true if we should take \p B. +bool ThreadSafetyAnalyzer::join(const FactEntry &A, const FactEntry &B, + bool CanModify) { if (A.kind() != B.kind()) { // For managed capabilities, the destructor should unlock in the right mode // anyway. For asserted capabilities no unlocking is needed. if ((A.managed() || A.asserted()) && (B.managed() || B.asserted())) { - // The shared capability subsumes the exclusive capability. - return B.kind() == LK_Shared; - } else { - Handler.handleExclusiveAndShared("mutex", B.toString(), B.loc(), A.loc()); - // Take the exclusive capability to reduce further warnings. - return B.kind() == LK_Exclusive; + // The shared capability subsumes the exclusive capability, if possible. + bool ShouldTakeB = B.kind() == LK_Shared; + if (CanModify || !ShouldTakeB) + return ShouldTakeB; } + Handler.handleExclusiveAndShared("mutex", B.toString(), B.loc(), A.loc()); + // Take the exclusive capability to reduce further warnings. + return CanModify && B.kind() == LK_Exclusive; } else { // The non-asserted capability is the one we want to track. - return A.asserted() && !B.asserted(); + return CanModify && A.asserted() && !B.asserted(); } } @@ -2237,8 +2240,8 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &EntrySet, FactSet::iterator EntryIt = EntrySet.findLockIter(FactMan, ExitFact); if (EntryIt != EntrySet.end()) { - if (join(FactMan[*EntryIt], ExitFact) && - EntryLEK == LEK_LockedSomePredecessors) + if (join(FactMan[*EntryIt], ExitFact, + EntryLEK != LEK_LockedSomeLoopIterations)) *EntryIt = Fact; } else if (!ExitFact.managed()) { ExitFact.handleRemovalFromIntersection(ExitSet, FactMan, JoinLoc, |