[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)
Endre Fülöp via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 14 18:01:35 PDT 2024
================
@@ -70,73 +202,121 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
} // end anonymous namespace
-REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
+REGISTER_LIST_WITH_PROGRAMSTATE(ActiveCritSections, CritSectionMarker)
-void BlockInCriticalSectionChecker::initIdentifierInfo(ASTContext &Ctx) const {
- if (!IdentifierInfoInitialized) {
- /* In case of checking C code, or when the corresponding headers are not
- * included, we might end up query the identifier table every time when this
- * function is called instead of early returning it. To avoid this, a bool
- * variable (IdentifierInfoInitialized) is used and the function will be run
- * only once. */
- IILockGuard = &Ctx.Idents.get(ClassLockGuard);
- IIUniqueLock = &Ctx.Idents.get(ClassUniqueLock);
- IdentifierInfoInitialized = true;
- }
-}
+namespace std {
+// Iterator traits for ImmutableList data structure
+// that enable the use of STL algorithms.
+// TODO: Move these to llvm::ImmutableList when overhauling immutable data
+// structures for proper iterator concept support.
+template <>
+struct iterator_traits<
+ typename llvm::ImmutableList<CritSectionMarker>::iterator> {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = CritSectionMarker;
+ using difference_type = std::ptrdiff_t;
+ using reference = CritSectionMarker &;
+ using pointer = CritSectionMarker *;
+};
+} // namespace std
-bool BlockInCriticalSectionChecker::isBlockingFunction(const CallEvent &Call) const {
- return matchesAny(Call, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn);
+std::optional<MutexDescriptor>
+BlockInCriticalSectionChecker::checkLock(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *LockDescriptor =
+ llvm::find_if(MutexDescriptors, [&Call](auto &&LockFn) {
+ return std::visit(
+ [&Call](auto &&Descriptor) { return Descriptor.matchesLock(Call); },
+ LockFn);
+ });
+ if (LockDescriptor != MutexDescriptors.end())
+ return *LockDescriptor;
+ return std::nullopt;
}
-bool BlockInCriticalSectionChecker::isLockFunction(const CallEvent &Call) const {
- if (const auto *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
- auto IdentifierInfo = Ctor->getDecl()->getParent()->getIdentifier();
- if (IdentifierInfo == IILockGuard || IdentifierInfo == IIUniqueLock)
- return true;
- }
+void BlockInCriticalSectionChecker::handleLock(
+ const MutexDescriptor &LockDescriptor, const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *MutexRegion = std::visit(
+ [&Call](auto &&Descriptor) { return Descriptor.getLockRegion(Call); },
+ LockDescriptor);
+ if (!MutexRegion)
+ return;
+
+ const auto MarkToAdd = CritSectionMarker{Call.getOriginExpr(), MutexRegion};
+ ProgramStateRef StateWithLockEvent =
+ C.getState()->add<ActiveCritSections>(MarkToAdd);
+ C.addTransition(StateWithLockEvent, createCritSectionNote(MarkToAdd, C));
+}
- return matchesAny(Call, LockFn, PthreadLockFn, PthreadTryLockFn, MtxLock,
- MtxTimedLock, MtxTryLock);
+std::optional<MutexDescriptor>
+BlockInCriticalSectionChecker::checkUnlock(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *UnlockDescriptor =
+ llvm::find_if(MutexDescriptors, [&Call](auto &&UnlockFn) {
+ return std::visit(
+ [&Call](auto &&Descriptor) {
+ return Descriptor.matchesUnlock(Call);
+ },
+ UnlockFn);
+ });
+ if (UnlockDescriptor != MutexDescriptors.end())
+ return *UnlockDescriptor;
+ return std::nullopt;
----------------
gamesh411 wrote:
I think I have fixed most of the code duplication, thanks for the suggestions 👍
https://github.com/llvm/llvm-project/pull/80029
More information about the cfe-commits
mailing list