[clang] [clang][analyzer] Add note tags to alpha.unix.BlockInCriticalSection (PR #80029)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 30 08:41:41 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Endre Fülöp (gamesh411)
<details>
<summary>Changes</summary>
checker
On entering a critical section, a note tag is now placed along the bugpath.
---
Full diff: https://github.com/llvm/llvm-project/pull/80029.diff
2 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp (+17-2)
- (modified) clang/test/Analysis/block-in-critical-section.cpp (+59-18)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index 66e080adb1382..2b9b56ecdd374 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -57,6 +57,8 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
const CallEvent &call,
CheckerContext &C) const;
+ const NoteTag *createCriticalSectionNote(CheckerContext &C) const;
+
public:
bool isBlockingFunction(const CallEvent &Call) const;
bool isLockFunction(const CallEvent &Call) const;
@@ -126,8 +128,9 @@ void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call,
State = State->set<MutexCounter>(--mutexCount);
C.addTransition(State);
} else if (isLockFunction(Call)) {
+ const NoteTag *Note = createCriticalSectionNote(C);
State = State->set<MutexCounter>(++mutexCount);
- C.addTransition(State);
+ C.addTransition(State, Note);
} else if (mutexCount > 0) {
SymbolRef BlockDesc = Call.getReturnValue().getAsSymbol();
reportBlockInCritSection(BlockDesc, Call, C);
@@ -151,10 +154,22 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection(
C.emitReport(std::move(R));
}
+const NoteTag *BlockInCriticalSectionChecker::createCriticalSectionNote(
+ CheckerContext &C) const {
+ const BugType *BT = &this->BlockInCritSectionBugType;
+ return C.getNoteTag(
+ [BT](PathSensitiveBugReport &BR, llvm::raw_ostream &OS) {
+ if(&BR.getBugType() != BT)
+ return;
+ OS << "Entering critical section here";
+ });
+}
+
void ento::registerBlockInCriticalSectionChecker(CheckerManager &mgr) {
mgr.registerChecker<BlockInCriticalSectionChecker>();
}
-bool ento::shouldRegisterBlockInCriticalSectionChecker(const CheckerManager &mgr) {
+bool ento::shouldRegisterBlockInCriticalSectionChecker(
+ const CheckerManager &mgr) {
return true;
}
diff --git a/clang/test/Analysis/block-in-critical-section.cpp b/clang/test/Analysis/block-in-critical-section.cpp
index fcf6188fc033e..93d46c741e16f 100644
--- a/clang/test/Analysis/block-in-critical-section.cpp
+++ b/clang/test/Analysis/block-in-critical-section.cpp
@@ -1,4 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 \
+// RUN: -analyzer-checker=alpha.unix.BlockInCriticalSection \
+// RUN: -std=c++11 \
+// RUN: -analyzer-output text \
+// RUN: -verify %s
void sleep(int x) {}
@@ -21,7 +25,7 @@ template<typename T>
struct not_real_lock {
not_real_lock<T>(std::mutex) {}
};
-}
+} // namespace std
void getc() {}
void fgets() {}
@@ -39,81 +43,115 @@ void mtx_unlock() {}
void testBlockInCriticalSectionWithStdMutex() {
std::mutex m;
- m.lock();
+ m.lock(); // expected-note 5{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'getc' inside of critical section}}
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'fgets' inside of critical section}}
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'read' inside of critical section}}
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'recv' inside of critical section}}
m.unlock();
}
void testBlockInCriticalSectionWithPthreadMutex() {
- pthread_mutex_lock();
+ pthread_mutex_lock(); // expected-note 10{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'getc' inside of critical section}}
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'fgets' inside of critical section}}
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'read' inside of critical section}}
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'recv' inside of critical section}}
pthread_mutex_unlock();
- pthread_mutex_trylock();
+ pthread_mutex_trylock(); // expected-note 5{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'getc' inside of critical section}}
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'fgets' inside of critical section}}
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'read' inside of critical section}}
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'recv' inside of critical section}}
pthread_mutex_unlock();
}
void testBlockInCriticalSectionC11Locks() {
- mtx_lock();
+ mtx_lock(); // expected-note 15{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'getc' inside of critical section}}
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'fgets' inside of critical section}}
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'read' inside of critical section}}
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'recv' inside of critical section}}
mtx_unlock();
- mtx_timedlock();
+ mtx_timedlock(); // expected-note 10{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'getc' inside of critical section}}
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'fgets' inside of critical section}}
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'read' inside of critical section}}
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'recv' inside of critical section}}
mtx_unlock();
- mtx_trylock();
+ mtx_trylock(); // expected-note 5{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'getc' inside of critical section}}
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'fgets' inside of critical section}}
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'read' inside of critical section}}
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'recv' inside of critical section}}
mtx_unlock();
}
void testBlockInCriticalSectionWithNestedMutexes() {
std::mutex m, n, k;
- m.lock();
- n.lock();
- k.lock();
+ m.lock(); // expected-note 3{{Entering critical section here}}
+ n.lock(); // expected-note 3{{Entering critical section here}}
+ k.lock(); // expected-note 3{{Entering critical section here}}
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
k.unlock();
sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
n.unlock();
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
m.unlock();
sleep(3); // no-warning
}
void f() {
sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
}
void testBlockInCriticalSectionInterProcedural() {
std::mutex m;
- m.lock();
- f();
+ m.lock(); // expected-note {{Entering critical section here}}
+ f(); // expected-note {{Calling 'f'}}
m.unlock();
}
@@ -121,8 +159,9 @@ void testBlockInCriticalSectionUnexpectedUnlock() {
std::mutex m;
m.unlock();
sleep(1); // no-warning
- m.lock();
+ m.lock(); // expected-note {{Entering critical section here}}
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
}
void testBlockInCriticalSectionLockGuard() {
@@ -130,12 +169,13 @@ void testBlockInCriticalSectionLockGuard() {
std::not_real_lock<std::mutex> not_real_lock(g_mutex);
sleep(1); // no-warning
- std::lock_guard<std::mutex> lock(g_mutex);
+ std::lock_guard<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}}
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
}
void testBlockInCriticalSectionLockGuardNested() {
- testBlockInCriticalSectionLockGuard();
+ testBlockInCriticalSectionLockGuard(); // expected-note {{Calling 'testBlockInCriticalSectionLockGuard'}}
sleep(1); // no-warning
}
@@ -144,11 +184,12 @@ void testBlockInCriticalSectionUniqueLock() {
std::not_real_lock<std::mutex> not_real_lock(g_mutex);
sleep(1); // no-warning
- std::unique_lock<std::mutex> lock(g_mutex);
+ std::unique_lock<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}}
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
+ // expected-note at -1 {{Call to blocking function 'sleep' inside of critical section}}
}
void testBlockInCriticalSectionUniqueLockNested() {
- testBlockInCriticalSectionUniqueLock();
+ testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}}
sleep(1); // no-warning
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/80029
More information about the cfe-commits
mailing list