[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