@@ -1050,6 +1050,8 @@ class ThreadSafetyAnalyzer {
10501050 const CFGBlock* PredBlock,
10511051 const CFGBlock *CurrBlock);
10521052
1053+ bool join (const FactEntry &a, const FactEntry &b);
1054+
10531055 void intersectAndWarn (FactSet &FSet1, const FactSet &FSet2,
10541056 SourceLocation JoinLoc, LockErrorKind LEK1,
10551057 LockErrorKind LEK2);
@@ -2186,6 +2188,28 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) {
21862188 }
21872189}
21882190
2191+ // / Given two facts merging on a join point, decide whether to warn and which
2192+ // / one to keep.
2193+ // /
2194+ // / \return false if we should keep \p A, true if we should keep \p B.
2195+ bool ThreadSafetyAnalyzer::join (const FactEntry &A, const FactEntry &B) {
2196+ if (A.kind () != B.kind ()) {
2197+ // For managed capabilities, the destructor should unlock in the right mode
2198+ // anyway. For asserted capabilities no unlocking is needed.
2199+ if ((A.managed () || A.asserted ()) && (B.managed () || B.asserted ())) {
2200+ // The shared capability subsumes the exclusive capability.
2201+ return B.kind () == LK_Shared;
2202+ } else {
2203+ Handler.handleExclusiveAndShared (" mutex" , B.toString (), B.loc (), A.loc ());
2204+ // Take the exclusive capability to reduce further warnings.
2205+ return B.kind () == LK_Exclusive;
2206+ }
2207+ } else {
2208+ // The non-asserted capability is the one we want to track.
2209+ return A.asserted () && !B.asserted ();
2210+ }
2211+ }
2212+
21892213// / Compute the intersection of two locksets and issue warnings for any
21902214// / locks in the symmetric difference.
21912215// /
@@ -2213,20 +2237,8 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
22132237
22142238 FactSet::iterator Iter1 = FSet1.findLockIter (FactMan, LDat2);
22152239 if (Iter1 != FSet1.end ()) {
2216- const FactEntry &LDat1 = FactMan[*Iter1];
2217- if (LDat1.kind () != LDat2.kind ()) {
2218- Handler.handleExclusiveAndShared (" mutex" , LDat2.toString (), LDat2.loc (),
2219- LDat1.loc ());
2220- if (LEK1 == LEK_LockedSomePredecessors &&
2221- LDat1.kind () != LK_Exclusive) {
2222- // Take the exclusive lock, which is the one in FSet2.
2223- *Iter1 = Fact;
2224- }
2225- } else if (LEK1 == LEK_LockedSomePredecessors && LDat1.asserted () &&
2226- !LDat2.asserted ()) {
2227- // The non-asserted lock in FSet2 is the one we want to track.
2240+ if (join (FactMan[*Iter1], LDat2) && LEK1 == LEK_LockedSomePredecessors)
22282241 *Iter1 = Fact;
2229- }
22302242 } else {
22312243 LDat2.handleRemovalFromIntersection (FSet2, FactMan, JoinLoc, LEK1,
22322244 Handler);
0 commit comments