Thread safety analysis: Store CapabilityExprs in ScopedLockableFactEntry (NFC)

For now this doesn't make a whole lot of sense, but it will allow us to
store the capability kind in a CapabilityExpr and make sure it doesn't
get lost. The capabilities managed by a scoped lockable can of course be
of different kind, so we'll need to store that per entry.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D124128
This commit is contained in:
Aaron Puchert 2022-04-29 22:11:20 +02:00
parent dd1790cd05
commit d65c922450
1 changed files with 23 additions and 25 deletions

View File

@ -41,7 +41,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@ -897,25 +896,27 @@ private:
UCK_ReleasedExclusive, ///< Exclusive capability that was released.
};
using UnderlyingCapability =
llvm::PointerIntPair<const til::SExpr *, 2, UnderlyingCapabilityKind>;
struct UnderlyingCapability {
CapabilityExpr Cap;
UnderlyingCapabilityKind Kind;
};
SmallVector<UnderlyingCapability, 4> UnderlyingMutexes;
SmallVector<UnderlyingCapability, 2> UnderlyingMutexes;
public:
ScopedLockableFactEntry(const CapabilityExpr &CE, SourceLocation Loc)
: FactEntry(CE, LK_Exclusive, Loc, Acquired) {}
void addLock(const CapabilityExpr &M) {
UnderlyingMutexes.emplace_back(M.sexpr(), UCK_Acquired);
UnderlyingMutexes.push_back(UnderlyingCapability{M, UCK_Acquired});
}
void addExclusiveUnlock(const CapabilityExpr &M) {
UnderlyingMutexes.emplace_back(M.sexpr(), UCK_ReleasedExclusive);
UnderlyingMutexes.push_back(UnderlyingCapability{M, UCK_ReleasedExclusive});
}
void addSharedUnlock(const CapabilityExpr &M) {
UnderlyingMutexes.emplace_back(M.sexpr(), UCK_ReleasedShared);
UnderlyingMutexes.push_back(UnderlyingCapability{M, UCK_ReleasedShared});
}
void
@ -923,15 +924,13 @@ public:
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const override {
for (const auto &UnderlyingMutex : UnderlyingMutexes) {
const auto *Entry = FSet.findLock(
FactMan, CapabilityExpr(UnderlyingMutex.getPointer(), false));
if ((UnderlyingMutex.getInt() == UCK_Acquired && Entry) ||
(UnderlyingMutex.getInt() != UCK_Acquired && !Entry)) {
const auto *Entry = FSet.findLock(FactMan, UnderlyingMutex.Cap);
if ((UnderlyingMutex.Kind == UCK_Acquired && Entry) ||
(UnderlyingMutex.Kind != UCK_Acquired && !Entry)) {
// If this scoped lock manages another mutex, and if the underlying
// mutex is still/not held, then warn about the underlying mutex.
Handler.handleMutexHeldEndOfScope(
"mutex", sx::toString(UnderlyingMutex.getPointer()), loc(), JoinLoc,
LEK);
"mutex", UnderlyingMutex.Cap.toString(), loc(), JoinLoc, LEK);
}
}
}
@ -940,13 +939,12 @@ public:
ThreadSafetyHandler &Handler,
StringRef DiagKind) const override {
for (const auto &UnderlyingMutex : UnderlyingMutexes) {
CapabilityExpr UnderCp(UnderlyingMutex.getPointer(), false);
if (UnderlyingMutex.getInt() == UCK_Acquired)
lock(FSet, FactMan, UnderCp, entry.kind(), entry.loc(), &Handler,
DiagKind);
if (UnderlyingMutex.Kind == UCK_Acquired)
lock(FSet, FactMan, UnderlyingMutex.Cap, entry.kind(), entry.loc(),
&Handler, DiagKind);
else
unlock(FSet, FactMan, UnderCp, entry.loc(), &Handler, DiagKind);
unlock(FSet, FactMan, UnderlyingMutex.Cap, entry.loc(), &Handler,
DiagKind);
}
}
@ -956,18 +954,18 @@ public:
StringRef DiagKind) const override {
assert(!Cp.negative() && "Managing object cannot be negative.");
for (const auto &UnderlyingMutex : UnderlyingMutexes) {
CapabilityExpr UnderCp(UnderlyingMutex.getPointer(), false);
// Remove/lock the underlying mutex if it exists/is still unlocked; warn
// on double unlocking/locking if we're not destroying the scoped object.
ThreadSafetyHandler *TSHandler = FullyRemove ? nullptr : &Handler;
if (UnderlyingMutex.getInt() == UCK_Acquired) {
unlock(FSet, FactMan, UnderCp, UnlockLoc, TSHandler, DiagKind);
if (UnderlyingMutex.Kind == UCK_Acquired) {
unlock(FSet, FactMan, UnderlyingMutex.Cap, UnlockLoc, TSHandler,
DiagKind);
} else {
LockKind kind = UnderlyingMutex.getInt() == UCK_ReleasedShared
LockKind kind = UnderlyingMutex.Kind == UCK_ReleasedShared
? LK_Shared
: LK_Exclusive;
lock(FSet, FactMan, UnderCp, kind, UnlockLoc, TSHandler, DiagKind);
lock(FSet, FactMan, UnderlyingMutex.Cap, kind, UnlockLoc, TSHandler,
DiagKind);
}
}
if (FullyRemove)