1 //===- ThreadSafety.h -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //
11 // A intra-procedural analysis for thread safety (e.g. deadlocks and race
12 // conditions), based off of an annotation system.
13 //
14 // See http://clang.llvm.org/docs/LanguageExtensions.html#thread-safety-annotation-checking
15 // for more information.
16 //
17 //===----------------------------------------------------------------------===//
18 
19 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
20 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
21 
22 #include "clang/Basic/SourceLocation.h"
23 #include "llvm/ADT/StringRef.h"
24 
25 namespace clang {
26 
27 class AnalysisDeclContext;
28 class FunctionDecl;
29 class NamedDecl;
30 
31 namespace threadSafety {
32 
33 class 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.
37 enum ProtectedOperationKind {
38   /// Dereferencing a variable (e.g. p in *p = 5;)
39   POK_VarDereference,
40 
41   /// Reading or writing a variable (e.g. x in x = 5;)
42   POK_VarAccess,
43 
44   /// Making a function call (e.g. fool())
45   POK_FunctionCall,
46 
47   /// Passing a guarded variable by reference.
48   POK_PassByRef,
49 
50   /// Passing a pt-guarded variable by reference.
51   POK_PtPassByRef
52 };
53 
54 /// This enum distinguishes between different kinds of lock actions. For
55 /// example, it is an error to write a variable protected by shared version of a
56 /// mutex.
57 enum LockKind {
58   /// Shared/reader lock of a mutex.
59   LK_Shared,
60 
61   /// Exclusive/writer lock of a mutex.
62   LK_Exclusive,
63 
64   /// Can be either Shared or Exclusive.
65   LK_Generic
66 };
67 
68 /// This enum distinguishes between different ways to access (read or write) a
69 /// variable.
70 enum AccessKind {
71   /// Reading a variable.
72   AK_Read,
73 
74   /// Writing a variable.
75   AK_Written
76 };
77 
78 /// This enum distinguishes between different situations where we warn due to
79 /// inconsistent locking.
80 /// \enum SK_LockedSomeLoopIterations -- a mutex is locked for some but not all
81 /// loop iterations.
82 /// \enum SK_LockedSomePredecessors -- a mutex is locked in some but not all
83 /// predecessors of a CFGBlock.
84 /// \enum SK_LockedAtEndOfFunction -- a mutex is still locked at the end of a
85 /// function.
86 enum LockErrorKind {
87   LEK_LockedSomeLoopIterations,
88   LEK_LockedSomePredecessors,
89   LEK_LockedAtEndOfFunction,
90   LEK_NotLockedAtEndOfFunction
91 };
92 
93 /// Handler class for thread safety warnings.
94 class ThreadSafetyHandler {
95 public:
96   using Name = StringRef;
97 
98   ThreadSafetyHandler() = default;
99   virtual ~ThreadSafetyHandler();
100 
101   /// Warn about lock expressions which fail to resolve to lockable objects.
102   /// \param Kind -- the capability's name parameter (role, mutex, etc).
103   /// \param Loc -- the SourceLocation of the unresolved expression.
handleInvalidLockExp(StringRef Kind,SourceLocation Loc)104   virtual void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) {}
105 
106   /// Warn about unlock function calls that do not have a prior matching lock
107   /// expression.
108   /// \param Kind -- the capability's name parameter (role, mutex, etc).
109   /// \param LockName -- A StringRef name for the lock expression, to be printed
110   /// in the error message.
111   /// \param Loc -- The SourceLocation of the Unlock
handleUnmatchedUnlock(StringRef Kind,Name LockName,SourceLocation Loc)112   virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
113                                      SourceLocation Loc) {}
114 
115   /// Warn about an unlock function call that attempts to unlock a lock with
116   /// the incorrect lock kind. For instance, a shared lock being unlocked
117   /// exclusively, or vice versa.
118   /// \param LockName -- A StringRef name for the lock expression, to be printed
119   /// in the error message.
120   /// \param Kind -- the capability's name parameter (role, mutex, etc).
121   /// \param Expected -- the kind of lock expected.
122   /// \param Received -- the kind of lock received.
123   /// \param Loc -- The SourceLocation of the Unlock.
handleIncorrectUnlockKind(StringRef Kind,Name LockName,LockKind Expected,LockKind Received,SourceLocation Loc)124   virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
125                                          LockKind Expected, LockKind Received,
126                                          SourceLocation Loc) {}
127 
128   /// Warn about lock function calls for locks which are already held.
129   /// \param Kind -- the capability's name parameter (role, mutex, etc).
130   /// \param LockName -- A StringRef name for the lock expression, to be printed
131   /// in the error message.
132   /// \param Loc -- The location of the second lock expression.
handleDoubleLock(StringRef Kind,Name LockName,SourceLocation Loc)133   virtual void handleDoubleLock(StringRef Kind, Name LockName,
134                                 SourceLocation Loc) {}
135 
136   /// Warn about situations where a mutex is sometimes held and sometimes not.
137   /// The three situations are:
138   /// 1. a mutex is locked on an "if" branch but not the "else" branch,
139   /// 2, or a mutex is only held at the start of some loop iterations,
140   /// 3. or when a mutex is locked but not unlocked inside a function.
141   /// \param Kind -- the capability's name parameter (role, mutex, etc).
142   /// \param LockName -- A StringRef name for the lock expression, to be printed
143   /// in the error message.
144   /// \param LocLocked -- The location of the lock expression where the mutex is
145   ///               locked
146   /// \param LocEndOfScope -- The location of the end of the scope where the
147   ///               mutex is no longer held
148   /// \param LEK -- which of the three above cases we should warn for
handleMutexHeldEndOfScope(StringRef Kind,Name LockName,SourceLocation LocLocked,SourceLocation LocEndOfScope,LockErrorKind LEK)149   virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
150                                          SourceLocation LocLocked,
151                                          SourceLocation LocEndOfScope,
152                                          LockErrorKind LEK) {}
153 
154   /// Warn when a mutex is held exclusively and shared at the same point. For
155   /// example, if a mutex is locked exclusively during an if branch and shared
156   /// during the else branch.
157   /// \param Kind -- the capability's name parameter (role, mutex, etc).
158   /// \param LockName -- A StringRef name for the lock expression, to be printed
159   /// in the error message.
160   /// \param Loc1 -- The location of the first lock expression.
161   /// \param Loc2 -- The location of the second lock expression.
handleExclusiveAndShared(StringRef Kind,Name LockName,SourceLocation Loc1,SourceLocation Loc2)162   virtual void handleExclusiveAndShared(StringRef Kind, Name LockName,
163                                         SourceLocation Loc1,
164                                         SourceLocation Loc2) {}
165 
166   /// Warn when a protected operation occurs while no locks are held.
167   /// \param Kind -- the capability's name parameter (role, mutex, etc).
168   /// \param D -- The decl for the protected variable or function
169   /// \param POK -- The kind of protected operation (e.g. variable access)
170   /// \param AK -- The kind of access (i.e. read or write) that occurred
171   /// \param Loc -- The location of the protected operation.
handleNoMutexHeld(StringRef Kind,const NamedDecl * D,ProtectedOperationKind POK,AccessKind AK,SourceLocation Loc)172   virtual void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
173                                  ProtectedOperationKind POK, AccessKind AK,
174                                  SourceLocation Loc) {}
175 
176   /// Warn when a protected operation occurs while the specific mutex protecting
177   /// the operation is not locked.
178   /// \param Kind -- the capability's name parameter (role, mutex, etc).
179   /// \param D -- The decl for the protected variable or function
180   /// \param POK -- The kind of protected operation (e.g. variable access)
181   /// \param LockName -- A StringRef name for the lock expression, to be printed
182   /// in the error message.
183   /// \param LK -- The kind of access (i.e. read or write) that occurred
184   /// \param Loc -- The location of the protected operation.
185   virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
186                                   ProtectedOperationKind POK, Name LockName,
187                                   LockKind LK, SourceLocation Loc,
188                                   Name *PossibleMatch = nullptr) {}
189 
190   /// Warn when acquiring a lock that the negative capability is not held.
191   /// \param Kind -- the capability's name parameter (role, mutex, etc).
192   /// \param LockName -- The name for the lock expression, to be printed in the
193   /// diagnostic.
194   /// \param Neg -- The name of the negative capability to be printed in the
195   /// diagnostic.
196   /// \param Loc -- The location of the protected operation.
handleNegativeNotHeld(StringRef Kind,Name LockName,Name Neg,SourceLocation Loc)197   virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
198                                      SourceLocation Loc) {}
199 
200   /// Warn when a function is called while an excluded mutex is locked. For
201   /// example, the mutex may be locked inside the function.
202   /// \param Kind -- the capability's name parameter (role, mutex, etc).
203   /// \param FunName -- The name of the function
204   /// \param LockName -- A StringRef name for the lock expression, to be printed
205   /// in the error message.
206   /// \param Loc -- The location of the function call.
handleFunExcludesLock(StringRef Kind,Name FunName,Name LockName,SourceLocation Loc)207   virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
208                                      Name LockName, SourceLocation Loc) {}
209 
210   /// Warn that L1 cannot be acquired before L2.
handleLockAcquiredBefore(StringRef Kind,Name L1Name,Name L2Name,SourceLocation Loc)211   virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
212                                         Name L2Name, SourceLocation Loc) {}
213 
214   /// Warn that there is a cycle in acquired_before/after dependencies.
handleBeforeAfterCycle(Name L1Name,SourceLocation Loc)215   virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
216 
217   /// Called by the analysis when starting analysis of a function.
218   /// Used to issue suggestions for changes to annotations.
enterFunction(const FunctionDecl * FD)219   virtual void enterFunction(const FunctionDecl *FD) {}
220 
221   /// Called by the analysis when finishing analysis of a function.
leaveFunction(const FunctionDecl * FD)222   virtual void leaveFunction(const FunctionDecl *FD) {}
223 
issueBetaWarnings()224   bool issueBetaWarnings() { return IssueBetaWarnings; }
setIssueBetaWarnings(bool b)225   void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
226 
227 private:
228   bool IssueBetaWarnings = false;
229 };
230 
231 /// Check a function's CFG for thread-safety violations.
232 ///
233 /// We traverse the blocks in the CFG, compute the set of mutexes that are held
234 /// at the end of each block, and issue warnings for thread safety violations.
235 /// Each block in the CFG is traversed exactly once.
236 void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
237                              ThreadSafetyHandler &Handler,
238                              BeforeSet **Bset);
239 
240 void threadSafetyCleanup(BeforeSet *Cache);
241 
242 /// Helper function that returns a LockKind required for the given level
243 /// of access.
244 LockKind getLockKindFromAccessKind(AccessKind AK);
245 
246 } // namespace threadSafety
247 } // namespace clang
248 
249 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
250