diff options
author | Aaron Puchert <aaronpuchert@alice-dsl.net> | 2018-08-22 22:14:53 +0000 |
---|---|---|
committer | Aaron Puchert <aaronpuchert@alice-dsl.net> | 2018-08-22 22:14:53 +0000 |
commit | c3e37b7538e7ff16f65d7ead4c54419ce21299a5 (patch) | |
tree | 4663c5c9136cc254925ca6d5901090f7508c8f23 /clang/lib/Analysis/ThreadSafety.cpp | |
parent | 96e3cd85bd2ddf7cb059665d94f0f66887692042 (diff) | |
download | llvm-c3e37b7538e7ff16f65d7ead4c54419ce21299a5.zip llvm-c3e37b7538e7ff16f65d7ead4c54419ce21299a5.tar.gz llvm-c3e37b7538e7ff16f65d7ead4c54419ce21299a5.tar.bz2 |
Thread safety analysis: Allow relockable scopes
Summary:
It's already allowed to prematurely release a scoped lock, now we also
allow relocking it again, possibly even in another mode.
This is the second attempt, the first had been merged as r339456 and
reverted in r339558 because it caused a crash.
Reviewers: delesley, aaron.ballman
Reviewed By: delesley, aaron.ballman
Subscribers: hokein, cfe-commits
Differential Revision: https://reviews.llvm.org/D49885
llvm-svn: 340459
Diffstat (limited to 'clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r-- | clang/lib/Analysis/ThreadSafety.cpp | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 40a43792..67eb626 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -142,6 +142,9 @@ public: handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan, SourceLocation JoinLoc, LockErrorKind LEK, ThreadSafetyHandler &Handler) const = 0; + virtual void handleLock(FactSet &FSet, FactManager &FactMan, + const FactEntry &entry, ThreadSafetyHandler &Handler, + StringRef DiagKind) const = 0; virtual void handleUnlock(FactSet &FSet, FactManager &FactMan, const CapabilityExpr &Cp, SourceLocation UnlockLoc, bool FullyRemove, ThreadSafetyHandler &Handler, @@ -873,6 +876,12 @@ public: } } + void handleLock(FactSet &FSet, FactManager &FactMan, const FactEntry &entry, + ThreadSafetyHandler &Handler, + StringRef DiagKind) const override { + Handler.handleDoubleLock(DiagKind, entry.toString(), entry.loc()); + } + void handleUnlock(FactSet &FSet, FactManager &FactMan, const CapabilityExpr &Cp, SourceLocation UnlockLoc, bool FullyRemove, ThreadSafetyHandler &Handler, @@ -913,6 +922,23 @@ public: } } + void handleLock(FactSet &FSet, FactManager &FactMan, const FactEntry &entry, + ThreadSafetyHandler &Handler, + StringRef DiagKind) const override { + for (const auto *UnderlyingMutex : UnderlyingMutexes) { + CapabilityExpr UnderCp(UnderlyingMutex, false); + + // We're relocking the underlying mutexes. Warn on double locking. + if (FSet.findLock(FactMan, UnderCp)) + Handler.handleDoubleLock(DiagKind, UnderCp.toString(), entry.loc()); + else { + FSet.removeLock(FactMan, !UnderCp); + FSet.addLock(FactMan, llvm::make_unique<LockableFactEntry>( + UnderCp, entry.kind(), entry.loc())); + } + } + } + void handleUnlock(FactSet &FSet, FactManager &FactMan, const CapabilityExpr &Cp, SourceLocation UnlockLoc, bool FullyRemove, ThreadSafetyHandler &Handler, @@ -1251,9 +1277,9 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet, } // FIXME: Don't always warn when we have support for reentrant locks. - if (FSet.findLock(FactMan, *Entry)) { + if (FactEntry *Cp = FSet.findLock(FactMan, *Entry)) { if (!Entry->asserted()) - Handler.handleDoubleLock(DiagKind, Entry->toString(), Entry->loc()); + Cp->handleLock(FSet, FactMan, *Entry, Handler, DiagKind); } else { FSet.addLock(FactMan, std::move(Entry)); } |