clang 23.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/ArrayRef.h"
23#include "llvm/ADT/StringRef.h"
24
25namespace clang {
26
28class FunctionDecl;
29class NamedDecl;
30
31namespace threadSafety {
32
33class BeforeSet;
34
35/// This enum distinguishes between different kinds of operations that may
36/// need to be protected by locks. We use this enum in error handling.
38 /// Dereferencing a variable (e.g. p in *p = 5;)
40
41 /// Reading or writing a variable (e.g. x in x = 5;)
43
44 /// Making a function call (e.g. fool())
46
47 /// Passing a guarded variable by reference.
49
50 /// Passing a pt-guarded variable by reference.
52
53 /// Returning a guarded variable by reference.
55
56 /// Returning a pt-guarded variable by reference.
58
59 /// Passing pointer to a guarded variable.
61
62 /// Passing a pt-guarded pointer.
64
65 /// Returning pointer to a guarded variable.
67
68 /// Returning a pt-guarded pointer.
70};
71
72/// This enum distinguishes between different kinds of lock actions. For
73/// example, it is an error to write a variable protected by shared version of a
74/// mutex.
76 /// Shared/reader lock of a mutex.
78
79 /// Exclusive/writer lock of a mutex.
81
82 /// Can be either Shared or Exclusive.
84};
85
86/// This enum distinguishes between different ways to access (read or write) a
87/// variable.
89 /// Reading a variable.
91
92 /// Writing a variable.
94};
95
96/// This enum distinguishes between different situations where we warn due to
97/// inconsistent locking.
99 /// A capability is locked for some but not all loop iterations.
101 /// A capability is locked in some but not all predecessors of a CFGBlock.
103 /// A capability is still locked at the end of a function.
105 /// Expecting a capability to be held at the end of function.
107};
108
109/// Handler class for thread safety warnings.
111public:
112 using Name = StringRef;
113
116
117 /// Warn about lock expressions which fail to resolve to lockable objects.
118 /// \param Loc -- the SourceLocation of the unresolved expression.
120
121 /// Warn about unlock function calls that do not have a prior matching lock
122 /// expression.
123 /// \param Kind -- the capability's name parameter (role, mutex, etc).
124 /// \param LockName -- A StringRef name for the lock expression, to be printed
125 /// in the error message.
126 /// \param Loc -- The SourceLocation of the Unlock
127 /// \param LocPreviousUnlock -- If valid, the location of a previous Unlock.
128 virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
129 SourceLocation Loc,
130 SourceLocation LocPreviousUnlock) {}
131
132 /// Warn about an unlock function call that attempts to unlock a lock with
133 /// the incorrect lock kind. For instance, a shared lock being unlocked
134 /// exclusively, or vice versa.
135 /// \param LockName -- A StringRef name for the lock expression, to be printed
136 /// in the error message.
137 /// \param Kind -- the capability's name parameter (role, mutex, etc).
138 /// \param Expected -- the kind of lock expected.
139 /// \param Received -- the kind of lock received.
140 /// \param LocLocked -- The SourceLocation of the Lock.
141 /// \param LocUnlock -- The SourceLocation of the Unlock.
142 virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
143 LockKind Expected, LockKind Received,
144 SourceLocation LocLocked,
145 SourceLocation LocUnlock) {}
146
147 /// Warn about lock function calls for locks which are already held.
148 /// \param Kind -- the capability's name parameter (role, mutex, etc).
149 /// \param LockName -- A StringRef name for the lock expression, to be printed
150 /// in the error message.
151 /// \param LocLocked -- The location of the first lock expression.
152 /// \param LocDoubleLock -- The location of the second lock expression.
153 virtual void handleDoubleLock(StringRef Kind, Name LockName,
154 SourceLocation LocLocked,
155 SourceLocation LocDoubleLock) {}
156
157 /// Warn about situations where a mutex is sometimes held and sometimes not.
158 /// The three situations are:
159 /// 1. a mutex is locked on an "if" branch but not the "else" branch,
160 /// 2, or a mutex is only held at the start of some loop iterations,
161 /// 3. or when a mutex is locked but not unlocked inside a function.
162 /// \param Kind -- the capability's name parameter (role, mutex, etc).
163 /// \param LockName -- A StringRef name for the lock expression, to be printed
164 /// in the error message.
165 /// \param LocLocked -- The location of the lock expression where the mutex is
166 /// locked
167 /// \param LocEndOfScope -- The location of the end of the scope where the
168 /// mutex is no longer held
169 /// \param LEK -- which of the three above cases we should warn for
170 /// \param ReentrancyMismatch -- mismatching reentrancy depth
171 virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
172 SourceLocation LocLocked,
173 SourceLocation LocEndOfScope,
174 LockErrorKind LEK,
175 bool ReentrancyMismatch = false) {}
176
177 /// Warn when a mutex is held exclusively and shared at the same point. For
178 /// example, if a mutex is locked exclusively during an if branch and shared
179 /// during the else branch.
180 /// \param Kind -- the capability's name parameter (role, mutex, etc).
181 /// \param LockName -- A StringRef name for the lock expression, to be printed
182 /// in the error message.
183 /// \param Loc1 -- The location of the first lock expression.
184 /// \param Loc2 -- The location of the second lock expression.
185 virtual void handleExclusiveAndShared(StringRef Kind, Name LockName,
186 SourceLocation Loc1,
187 SourceLocation Loc2) {}
188
189 /// Warn when a protected operation occurs while no locks are held.
190 /// \param D -- The decl for the protected variable or function
191 /// \param POK -- The kind of protected operation (e.g. variable access)
192 /// \param AK -- The kind of access (i.e. read or write) that occurred
193 /// \param Loc -- The location of the protected operation.
196
197 /// Warn when a read of a multi-capability guarded_by variable occurs while
198 /// none of the listed capabilities are held.
199 /// \param D -- The decl for the protected variable
200 /// \param POK -- The kind of protected operation (e.g. variable access)
201 /// \param LockNames -- Names of the capabilities that were not held
202 /// \param Loc -- The location of the read
205 ArrayRef<StringRef> LockNames,
206 SourceLocation Loc) {}
207
208 /// Warn when a protected operation occurs while the specific mutex protecting
209 /// the operation is not locked.
210 /// \param Kind -- the capability's name parameter (role, mutex, etc).
211 /// \param D -- The decl for the protected variable or function
212 /// \param POK -- The kind of protected operation (e.g. variable access)
213 /// \param LockName -- A StringRef name for the lock expression, to be printed
214 /// in the error message.
215 /// \param LK -- The kind of access (i.e. read or write) that occurred
216 /// \param Loc -- The location of the protected operation.
217 virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
218 ProtectedOperationKind POK, Name LockName,
219 LockKind LK, SourceLocation Loc,
220 Name *PossibleMatch = nullptr) {}
221
222 /// Warn when acquiring a lock that the negative capability is not held.
223 /// \param Kind -- the capability's name parameter (role, mutex, etc).
224 /// \param LockName -- The name for the lock expression, to be printed in the
225 /// diagnostic.
226 /// \param Neg -- The name of the negative capability to be printed in the
227 /// diagnostic.
228 /// \param Loc -- The location of the protected operation.
229 virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
230 SourceLocation Loc) {}
231
232 /// Warn when calling a function that a negative capability is not held.
233 /// \param D -- The decl for the function requiring the negative capability.
234 /// \param LockName -- The name for the lock expression, to be printed in the
235 /// diagnostic.
236 /// \param Loc -- The location of the protected operation.
237 virtual void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
238 SourceLocation Loc) {}
239
240 /// Warn when a function is called while an excluded mutex is locked. For
241 /// example, the mutex may be locked inside the function.
242 /// \param Kind -- the capability's name parameter (role, mutex, etc).
243 /// \param FunName -- The name of the function
244 /// \param LockName -- A StringRef name for the lock expression, to be printed
245 /// in the error message.
246 /// \param Loc -- The location of the function call.
247 virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
248 Name LockName, SourceLocation Loc) {}
249
250 /// Warn when an actual underlying mutex of a scoped lockable does not match
251 /// the 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.
257 /// \param Actual -- The name of the actual mutex.
259 SourceLocation DLoc,
260 Name ScopeName, StringRef Kind,
261 Name Expected, Name Actual) {}
262
263 /// Warn when we get fewer underlying mutexes than expected.
264 /// \param Loc -- The location of the call expression.
265 /// \param DLoc -- The location of the function declaration.
266 /// \param ScopeName -- The name of the scope passed to the function.
267 /// \param Kind -- The kind of the expected mutex.
268 /// \param Expected -- The name of the expected mutex.
270 SourceLocation DLoc,
271 Name ScopeName, StringRef Kind,
272 Name Expected) {}
273
274 /// Warn when we get more underlying mutexes than expected.
275 /// \param Loc -- The location of the call expression.
276 /// \param DLoc -- The location of the function declaration.
277 /// \param ScopeName -- The name of the scope passed to the function.
278 /// \param Kind -- The kind of the actual mutex.
279 /// \param Actual -- The name of the actual mutex.
281 SourceLocation DLoc,
282 Name ScopeName,
283 StringRef Kind, Name Actual) {
284 }
285
286 /// Warn that L1 cannot be acquired before L2.
287 virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
288 Name L2Name, SourceLocation Loc) {}
289
290 /// Warn that there is a cycle in acquired_before/after dependencies.
291 virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
292
293 /// Called by the analysis when starting analysis of a function.
294 /// Used to issue suggestions for changes to annotations.
295 virtual void enterFunction(const FunctionDecl *FD) {}
296
297 /// Called by the analysis when finishing analysis of a function.
298 virtual void leaveFunction(const FunctionDecl *FD) {}
299
300 bool issueBetaWarnings() { return IssueBetaWarnings; }
301 void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
302
303private:
304 bool IssueBetaWarnings = false;
305};
306
307/// Check a function's CFG for thread-safety violations.
308///
309/// We traverse the blocks in the CFG, compute the set of mutexes that are held
310/// at the end of each block, and issue warnings for thread safety violations.
311/// Each block in the CFG is traversed exactly once.
313 ThreadSafetyHandler &Handler,
314 BeforeSet **Bset);
315
316void threadSafetyCleanup(BeforeSet *Cache);
317
318/// Helper function that returns a LockKind required for the given level
319/// of access.
321
322} // namespace threadSafety
323} // namespace clang
324
325#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:2015
This represents a decl that may have a name.
Definition Decl.h:274
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 handleGuardedByAnyReadNotHeld(const NamedDecl *D, ProtectedOperationKind POK, ArrayRef< StringRef > LockNames, SourceLocation Loc)
Warn when a read of a multi-capability guarded_by variable occurs while none of the listed capabiliti...
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.