clang 22.0.0git
ThreadSafety.h
Go to the documentation of this file.
1//===- ThreadSafety.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//
10// A intra-procedural analysis for thread safety (e.g. deadlocks and race
11// conditions), based off of an annotation system.
12//
13// See http://clang.llvm.org/docs/LanguageExtensions.html#thread-safety-annotation-checking
14// for more information.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
19#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
20
22#include "llvm/ADT/StringRef.h"
23
24namespace clang {
25
27class FunctionDecl;
28class NamedDecl;
29
30namespace threadSafety {
31
32class BeforeSet;
33
34/// This enum distinguishes between different kinds of operations that may
35/// need to be protected by locks. We use this enum in error handling.
37 /// Dereferencing a variable (e.g. p in *p = 5;)
39
40 /// Reading or writing a variable (e.g. x in x = 5;)
42
43 /// Making a function call (e.g. fool())
45
46 /// Passing a guarded variable by reference.
48
49 /// Passing a pt-guarded variable by reference.
51
52 /// Returning a guarded variable by reference.
54
55 /// Returning a pt-guarded variable by reference.
57
58 /// Passing pointer to a guarded variable.
60
61 /// Passing a pt-guarded pointer.
63
64 /// Returning pointer to a guarded variable.
66
67 /// Returning a pt-guarded pointer.
69};
70
71/// This enum distinguishes between different kinds of lock actions. For
72/// example, it is an error to write a variable protected by shared version of a
73/// mutex.
75 /// Shared/reader lock of a mutex.
77
78 /// Exclusive/writer lock of a mutex.
80
81 /// Can be either Shared or Exclusive.
83};
84
85/// This enum distinguishes between different ways to access (read or write) a
86/// variable.
88 /// Reading a variable.
90
91 /// Writing a variable.
93};
94
95/// This enum distinguishes between different situations where we warn due to
96/// inconsistent locking.
98 /// A capability is locked for some but not all loop iterations.
100 /// A capability is locked in some but not all predecessors of a CFGBlock.
102 /// A capability is still locked at the end of a function.
104 /// Expecting a capability to be held at the end of function.
106};
107
108/// Handler class for thread safety warnings.
110public:
111 using Name = StringRef;
112
115
116 /// Warn about lock expressions which fail to resolve to lockable objects.
117 /// \param Loc -- the SourceLocation of the unresolved expression.
119
120 /// Warn about unlock function calls that do not have a prior matching lock
121 /// expression.
122 /// \param Kind -- the capability's name parameter (role, mutex, etc).
123 /// \param LockName -- A StringRef name for the lock expression, to be printed
124 /// in the error message.
125 /// \param Loc -- The SourceLocation of the Unlock
126 /// \param LocPreviousUnlock -- If valid, the location of a previous Unlock.
127 virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
128 SourceLocation Loc,
129 SourceLocation LocPreviousUnlock) {}
130
131 /// Warn about an unlock function call that attempts to unlock a lock with
132 /// the incorrect lock kind. For instance, a shared lock being unlocked
133 /// exclusively, or vice versa.
134 /// \param LockName -- A StringRef name for the lock expression, to be printed
135 /// in the error message.
136 /// \param Kind -- the capability's name parameter (role, mutex, etc).
137 /// \param Expected -- the kind of lock expected.
138 /// \param Received -- the kind of lock received.
139 /// \param LocLocked -- The SourceLocation of the Lock.
140 /// \param LocUnlock -- The SourceLocation of the Unlock.
141 virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
142 LockKind Expected, LockKind Received,
143 SourceLocation LocLocked,
144 SourceLocation LocUnlock) {}
145
146 /// Warn about lock function calls for locks which are already held.
147 /// \param Kind -- the capability's name parameter (role, mutex, etc).
148 /// \param LockName -- A StringRef name for the lock expression, to be printed
149 /// in the error message.
150 /// \param LocLocked -- The location of the first lock expression.
151 /// \param LocDoubleLock -- The location of the second lock expression.
152 virtual void handleDoubleLock(StringRef Kind, Name LockName,
153 SourceLocation LocLocked,
154 SourceLocation LocDoubleLock) {}
155
156 /// Warn about situations where a mutex is sometimes held and sometimes not.
157 /// The three situations are:
158 /// 1. a mutex is locked on an "if" branch but not the "else" branch,
159 /// 2, or a mutex is only held at the start of some loop iterations,
160 /// 3. or when a mutex is locked but not unlocked inside a function.
161 /// \param Kind -- the capability's name parameter (role, mutex, etc).
162 /// \param LockName -- A StringRef name for the lock expression, to be printed
163 /// in the error message.
164 /// \param LocLocked -- The location of the lock expression where the mutex is
165 /// locked
166 /// \param LocEndOfScope -- The location of the end of the scope where the
167 /// mutex is no longer held
168 /// \param LEK -- which of the three above cases we should warn for
169 /// \param ReentrancyMismatch -- mismatching reentrancy depth
170 virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
171 SourceLocation LocLocked,
172 SourceLocation LocEndOfScope,
173 LockErrorKind LEK,
174 bool ReentrancyMismatch = false) {}
175
176 /// Warn when a mutex is held exclusively and shared at the same point. For
177 /// example, if a mutex is locked exclusively during an if branch and shared
178 /// during the else branch.
179 /// \param Kind -- the capability's name parameter (role, mutex, etc).
180 /// \param LockName -- A StringRef name for the lock expression, to be printed
181 /// in the error message.
182 /// \param Loc1 -- The location of the first lock expression.
183 /// \param Loc2 -- The location of the second lock expression.
184 virtual void handleExclusiveAndShared(StringRef Kind, Name LockName,
185 SourceLocation Loc1,
186 SourceLocation Loc2) {}
187
188 /// Warn when a protected operation occurs while no locks are held.
189 /// \param D -- The decl for the protected variable or function
190 /// \param POK -- The kind of protected operation (e.g. variable access)
191 /// \param AK -- The kind of access (i.e. read or write) that occurred
192 /// \param Loc -- The location of the protected operation.
195
196 /// Warn when a protected operation occurs while the specific mutex protecting
197 /// the operation is not locked.
198 /// \param Kind -- the capability's name parameter (role, mutex, etc).
199 /// \param D -- The decl for the protected variable or function
200 /// \param POK -- The kind of protected operation (e.g. variable access)
201 /// \param LockName -- A StringRef name for the lock expression, to be printed
202 /// in the error message.
203 /// \param LK -- The kind of access (i.e. read or write) that occurred
204 /// \param Loc -- The location of the protected operation.
205 virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
206 ProtectedOperationKind POK, Name LockName,
207 LockKind LK, SourceLocation Loc,
208 Name *PossibleMatch = nullptr) {}
209
210 /// Warn when acquiring a lock that the negative capability is not held.
211 /// \param Kind -- the capability's name parameter (role, mutex, etc).
212 /// \param LockName -- The name for the lock expression, to be printed in the
213 /// diagnostic.
214 /// \param Neg -- The name of the negative capability to be printed in the
215 /// diagnostic.
216 /// \param Loc -- The location of the protected operation.
217 virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
218 SourceLocation Loc) {}
219
220 /// Warn when calling a function that a negative capability is not held.
221 /// \param D -- The decl for the function requiring the negative capability.
222 /// \param LockName -- The name for the lock expression, to be printed in the
223 /// diagnostic.
224 /// \param Loc -- The location of the protected operation.
225 virtual void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
226 SourceLocation Loc) {}
227
228 /// Warn when a function is called while an excluded mutex is locked. For
229 /// example, the mutex may be locked inside the function.
230 /// \param Kind -- the capability's name parameter (role, mutex, etc).
231 /// \param FunName -- The name of the function
232 /// \param LockName -- A StringRef name for the lock expression, to be printed
233 /// in the error message.
234 /// \param Loc -- The location of the function call.
235 virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
236 Name LockName, SourceLocation Loc) {}
237
238 /// Warn when an actual underlying mutex of a scoped lockable does not match
239 /// the expected.
240 /// \param Loc -- The location of the call expression.
241 /// \param DLoc -- The location of the function declaration.
242 /// \param ScopeName -- The name of the scope passed to the function.
243 /// \param Kind -- The kind of the expected mutex.
244 /// \param Expected -- The name of the expected mutex.
245 /// \param Actual -- The name of the actual mutex.
247 SourceLocation DLoc,
248 Name ScopeName, StringRef Kind,
249 Name Expected, Name Actual) {}
250
251 /// Warn when we get fewer underlying mutexes than expected.
252 /// \param Loc -- The location of the call expression.
253 /// \param DLoc -- The location of the function declaration.
254 /// \param ScopeName -- The name of the scope passed to the function.
255 /// \param Kind -- The kind of the expected mutex.
256 /// \param Expected -- The name of the expected mutex.
258 SourceLocation DLoc,
259 Name ScopeName, StringRef Kind,
260 Name Expected) {}
261
262 /// Warn when we get more underlying mutexes than expected.
263 /// \param Loc -- The location of the call expression.
264 /// \param DLoc -- The location of the function declaration.
265 /// \param ScopeName -- The name of the scope passed to the function.
266 /// \param Kind -- The kind of the actual mutex.
267 /// \param Actual -- The name of the actual mutex.
269 SourceLocation DLoc,
270 Name ScopeName,
271 StringRef Kind, Name Actual) {
272 }
273
274 /// Warn that L1 cannot be acquired before L2.
275 virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
276 Name L2Name, SourceLocation Loc) {}
277
278 /// Warn that there is a cycle in acquired_before/after dependencies.
279 virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
280
281 /// Called by the analysis when starting analysis of a function.
282 /// Used to issue suggestions for changes to annotations.
283 virtual void enterFunction(const FunctionDecl *FD) {}
284
285 /// Called by the analysis when finishing analysis of a function.
286 virtual void leaveFunction(const FunctionDecl *FD) {}
287
288 bool issueBetaWarnings() { return IssueBetaWarnings; }
289 void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
290
291private:
292 bool IssueBetaWarnings = false;
293};
294
295/// Check a function's CFG for thread-safety violations.
296///
297/// We traverse the blocks in the CFG, compute the set of mutexes that are held
298/// at the end of each block, and issue warnings for thread safety violations.
299/// Each block in the CFG is traversed exactly once.
301 ThreadSafetyHandler &Handler,
302 BeforeSet **Bset);
303
304void threadSafetyCleanup(BeforeSet *Cache);
305
306/// Helper function that returns a LockKind required for the given level
307/// of access.
309
310} // namespace threadSafety
311} // namespace clang
312
313#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
Defines the clang::SourceLocation class and associated facilities.
__device__ __2f16 b
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a function declaration or definition.
Definition Decl.h:1999
This represents a decl that may have a name.
Definition Decl.h:273
Encodes a location in the source.
virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc)
Warn that there is a cycle in acquired_before/after dependencies.
virtual void handleExpectMoreUnderlyingMutexes(SourceLocation Loc, SourceLocation DLoc, Name ScopeName, StringRef Kind, Name Expected)
Warn when we get fewer underlying mutexes than expected.
virtual void handleInvalidLockExp(SourceLocation Loc)
Warn about lock expressions which fail to resolve to lockable objects.
virtual void handleUnmatchedUnderlyingMutexes(SourceLocation Loc, SourceLocation DLoc, Name ScopeName, StringRef Kind, Name Expected, Name Actual)
Warn when an actual underlying mutex of a scoped lockable does not match the expected.
virtual void handleExpectFewerUnderlyingMutexes(SourceLocation Loc, SourceLocation DLoc, Name ScopeName, StringRef Kind, Name Actual)
Warn when we get more underlying mutexes than expected.
virtual void enterFunction(const FunctionDecl *FD)
Called by the analysis when starting analysis of a function.
virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName, LockKind Expected, LockKind Received, SourceLocation LocLocked, SourceLocation LocUnlock)
Warn about an unlock function call that attempts to unlock a lock with the incorrect lock kind.
virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName, SourceLocation LocLocked, SourceLocation LocEndOfScope, LockErrorKind LEK, bool ReentrancyMismatch=false)
Warn about situations where a mutex is sometimes held and sometimes not.
virtual void leaveFunction(const FunctionDecl *FD)
Called by the analysis when finishing analysis of a function.
virtual void handleExclusiveAndShared(StringRef Kind, Name LockName, SourceLocation Loc1, SourceLocation Loc2)
Warn when a mutex is held exclusively and shared at the same point.
virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name, SourceLocation Loc)
Warn that L1 cannot be acquired before L2.
virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D, ProtectedOperationKind POK, Name LockName, LockKind LK, SourceLocation Loc, Name *PossibleMatch=nullptr)
Warn when a protected operation occurs while the specific mutex protecting the operation is not locke...
virtual void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, SourceLocation Loc)
Warn when a function is called while an excluded mutex is locked.
virtual void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, AccessKind AK, SourceLocation Loc)
Warn when a protected operation occurs while no locks are held.
virtual void handleNegativeNotHeld(const NamedDecl *D, Name LockName, SourceLocation Loc)
Warn when calling a function that a negative capability is not held.
virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName, SourceLocation Loc, SourceLocation LocPreviousUnlock)
Warn about unlock function calls that do not have a prior matching lock expression.
virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg, SourceLocation Loc)
Warn when acquiring a lock that the negative capability is not held.
virtual void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation LocLocked, SourceLocation LocDoubleLock)
Warn about lock function calls for locks which are already held.
LockKind getLockKindFromAccessKind(AccessKind AK)
Helper function that returns a LockKind required for the given level of access.
LockErrorKind
This enum distinguishes between different situations where we warn due to inconsistent locking.
@ LEK_NotLockedAtEndOfFunction
Expecting a capability to be held at the end of function.
@ LEK_LockedSomePredecessors
A capability is locked in some but not all predecessors of a CFGBlock.
@ LEK_LockedAtEndOfFunction
A capability is still locked at the end of a function.
@ LEK_LockedSomeLoopIterations
A capability is locked for some but not all loop iterations.
void threadSafetyCleanup(BeforeSet *Cache)
AccessKind
This enum distinguishes between different ways to access (read or write) a variable.
@ AK_Written
Writing a variable.
@ AK_Read
Reading a variable.
LockKind
This enum distinguishes between different kinds of lock actions.
@ LK_Shared
Shared/reader lock of a mutex.
@ LK_Exclusive
Exclusive/writer lock of a mutex.
@ LK_Generic
Can be either Shared or Exclusive.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC, ThreadSafetyHandler &Handler, BeforeSet **Bset)
Check a function's CFG for thread-safety violations.
ProtectedOperationKind
This enum distinguishes between different kinds of operations that may need to be protected by locks.
@ POK_PtPassByRef
Passing a pt-guarded variable by reference.
@ POK_PassPointer
Passing pointer to a guarded variable.
@ POK_VarDereference
Dereferencing a variable (e.g. p in *p = 5;)
@ POK_PassByRef
Passing a guarded variable by reference.
@ POK_ReturnByRef
Returning a guarded variable by reference.
@ POK_PtPassPointer
Passing a pt-guarded pointer.
@ POK_PtReturnPointer
Returning a pt-guarded pointer.
@ POK_VarAccess
Reading or writing a variable (e.g. x in x = 5;)
@ POK_FunctionCall
Making a function call (e.g. fool())
@ POK_ReturnPointer
Returning pointer to a guarded variable.
@ POK_PtReturnByRef
Returning a pt-guarded variable by reference.
The JSON file list parser is used to communicate input to InstallAPI.