Skip to content

Commit 54da4f5

Browse files
committed
[clang][analyzer] Add note tags to alpha.unix.BlockInCriticalSection
checker On entering a critical section, a note tag is now placed along the bugpath.
1 parent fd3edd4 commit 54da4f5

File tree

2 files changed

+76
-20
lines changed

2 files changed

+76
-20
lines changed

clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
5757
const CallEvent &call,
5858
CheckerContext &C) const;
5959

60+
const NoteTag *createCriticalSectionNote(CheckerContext &C) const;
61+
6062
public:
6163
bool isBlockingFunction(const CallEvent &Call) const;
6264
bool isLockFunction(const CallEvent &Call) const;
@@ -126,8 +128,9 @@ void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call,
126128
State = State->set<MutexCounter>(--mutexCount);
127129
C.addTransition(State);
128130
} else if (isLockFunction(Call)) {
131+
const NoteTag *Note = createCriticalSectionNote(C);
129132
State = State->set<MutexCounter>(++mutexCount);
130-
C.addTransition(State);
133+
C.addTransition(State, Note);
131134
} else if (mutexCount > 0) {
132135
SymbolRef BlockDesc = Call.getReturnValue().getAsSymbol();
133136
reportBlockInCritSection(BlockDesc, Call, C);
@@ -151,10 +154,22 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection(
151154
C.emitReport(std::move(R));
152155
}
153156

157+
const NoteTag *BlockInCriticalSectionChecker::createCriticalSectionNote(
158+
CheckerContext &C) const {
159+
const BugType *BT = &this->BlockInCritSectionBugType;
160+
return C.getNoteTag(
161+
[BT](PathSensitiveBugReport &BR, llvm::raw_ostream &OS) {
162+
if(&BR.getBugType() != BT)
163+
return;
164+
OS << "Entering critical section here";
165+
});
166+
}
167+
154168
void ento::registerBlockInCriticalSectionChecker(CheckerManager &mgr) {
155169
mgr.registerChecker<BlockInCriticalSectionChecker>();
156170
}
157171

158-
bool ento::shouldRegisterBlockInCriticalSectionChecker(const CheckerManager &mgr) {
172+
bool ento::shouldRegisterBlockInCriticalSectionChecker(
173+
const CheckerManager &mgr) {
159174
return true;
160175
}

clang/test/Analysis/block-in-critical-section.cpp

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
1+
// RUN: %clang_analyze_cc1 \
2+
// RUN: -analyzer-checker=alpha.unix.BlockInCriticalSection \
3+
// RUN: -std=c++11 \
4+
// RUN: -analyzer-output text \
5+
// RUN: -verify %s
26

37
void sleep(int x) {}
48

@@ -21,7 +25,7 @@ template<typename T>
2125
struct not_real_lock {
2226
not_real_lock<T>(std::mutex) {}
2327
};
24-
}
28+
} // namespace std
2529

2630
void getc() {}
2731
void fgets() {}
@@ -39,103 +43,139 @@ void mtx_unlock() {}
3943

4044
void testBlockInCriticalSectionWithStdMutex() {
4145
std::mutex m;
42-
m.lock();
46+
m.lock(); // expected-note 5{{Entering critical section here}}
4347
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
48+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
4449
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
50+
// expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
4551
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
52+
// expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
4653
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
54+
// expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
4755
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
56+
// expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
4857
m.unlock();
4958
}
5059

5160
void testBlockInCriticalSectionWithPthreadMutex() {
52-
pthread_mutex_lock();
61+
pthread_mutex_lock(); // expected-note 10{{Entering critical section here}}
5362
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
63+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
5464
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
65+
// expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
5566
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
67+
// expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
5668
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
69+
// expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
5770
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
71+
// expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
5872
pthread_mutex_unlock();
5973

60-
pthread_mutex_trylock();
74+
pthread_mutex_trylock(); // expected-note 5{{Entering critical section here}}
6175
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
76+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
6277
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
78+
// expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
6379
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
80+
// expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
6481
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
82+
// expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
6583
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
84+
// expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
6685
pthread_mutex_unlock();
6786
}
6887

6988
void testBlockInCriticalSectionC11Locks() {
70-
mtx_lock();
89+
mtx_lock(); // expected-note 15{{Entering critical section here}}
7190
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
91+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
7292
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
93+
// expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
7394
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
95+
// expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
7496
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
97+
// expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
7598
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
99+
// expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
76100
mtx_unlock();
77101

78-
mtx_timedlock();
102+
mtx_timedlock(); // expected-note 10{{Entering critical section here}}
79103
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
104+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
80105
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
106+
// expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
81107
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
108+
// expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
82109
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
110+
// expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
83111
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
112+
// expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
84113
mtx_unlock();
85114

86-
mtx_trylock();
115+
mtx_trylock(); // expected-note 5{{Entering critical section here}}
87116
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
117+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
88118
getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
119+
// expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
89120
fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
121+
// expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
90122
read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
123+
// expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
91124
recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
125+
// expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
92126
mtx_unlock();
93127
}
94128

95129
void testBlockInCriticalSectionWithNestedMutexes() {
96130
std::mutex m, n, k;
97-
m.lock();
98-
n.lock();
99-
k.lock();
131+
m.lock(); // expected-note 3{{Entering critical section here}}
132+
n.lock(); // expected-note 3{{Entering critical section here}}
133+
k.lock(); // expected-note 3{{Entering critical section here}}
100134
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
135+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
101136
k.unlock();
102137
sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
138+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
103139
n.unlock();
104140
sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
141+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
105142
m.unlock();
106143
sleep(3); // no-warning
107144
}
108145

109146
void f() {
110147
sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
148+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
111149
}
112150

113151
void testBlockInCriticalSectionInterProcedural() {
114152
std::mutex m;
115-
m.lock();
116-
f();
153+
m.lock(); // expected-note {{Entering critical section here}}
154+
f(); // expected-note {{Calling 'f'}}
117155
m.unlock();
118156
}
119157

120158
void testBlockInCriticalSectionUnexpectedUnlock() {
121159
std::mutex m;
122160
m.unlock();
123161
sleep(1); // no-warning
124-
m.lock();
162+
m.lock(); // expected-note {{Entering critical section here}}
125163
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
164+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
126165
}
127166

128167
void testBlockInCriticalSectionLockGuard() {
129168
std::mutex g_mutex;
130169
std::not_real_lock<std::mutex> not_real_lock(g_mutex);
131170
sleep(1); // no-warning
132171

133-
std::lock_guard<std::mutex> lock(g_mutex);
172+
std::lock_guard<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}}
134173
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
174+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
135175
}
136176

137177
void testBlockInCriticalSectionLockGuardNested() {
138-
testBlockInCriticalSectionLockGuard();
178+
testBlockInCriticalSectionLockGuard(); // expected-note {{Calling 'testBlockInCriticalSectionLockGuard'}}
139179
sleep(1); // no-warning
140180
}
141181

@@ -144,11 +184,12 @@ void testBlockInCriticalSectionUniqueLock() {
144184
std::not_real_lock<std::mutex> not_real_lock(g_mutex);
145185
sleep(1); // no-warning
146186

147-
std::unique_lock<std::mutex> lock(g_mutex);
187+
std::unique_lock<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}}
148188
sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
189+
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
149190
}
150191

151192
void testBlockInCriticalSectionUniqueLockNested() {
152-
testBlockInCriticalSectionUniqueLock();
193+
testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}}
153194
sleep(1); // no-warning
154195
}

0 commit comments

Comments
 (0)