• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_THREADSAFETY_H
20 #define LLVM_CLANG_THREADSAFETY_H
21 
22 #include "clang/Analysis/AnalysisContext.h"
23 #include "clang/Basic/SourceLocation.h"
24 #include "llvm/ADT/StringRef.h"
25 
26 namespace clang {
27 namespace thread_safety {
28 
29 /// This enum distinguishes between different kinds of operations that may
30 /// need to be protected by locks. We use this enum in error handling.
31 enum ProtectedOperationKind {
32   POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;)
33   POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;)
34   POK_FunctionCall ///< Making a function call (e.g. fool())
35 };
36 
37 /// This enum distinguishes between different kinds of lock actions. For
38 /// example, it is an error to write a variable protected by shared version of a
39 /// mutex.
40 enum LockKind {
41   LK_Shared, ///< Shared/reader lock of a mutex.
42   LK_Exclusive, ///< Exclusive/writer lock of a mutex.
43   LK_Generic  ///<  Can be either Shared or Exclusive
44 };
45 
46 /// This enum distinguishes between different ways to access (read or write) a
47 /// variable.
48 enum AccessKind {
49   AK_Read, ///< Reading a variable.
50   AK_Written ///< Writing a variable.
51 };
52 
53 /// This enum distinguishes between different situations where we warn due to
54 /// inconsistent locking.
55 /// \enum SK_LockedSomeLoopIterations -- a mutex is locked for some but not all
56 /// loop iterations.
57 /// \enum SK_LockedSomePredecessors -- a mutex is locked in some but not all
58 /// predecessors of a CFGBlock.
59 /// \enum SK_LockedAtEndOfFunction -- a mutex is still locked at the end of a
60 /// function.
61 enum LockErrorKind {
62   LEK_LockedSomeLoopIterations,
63   LEK_LockedSomePredecessors,
64   LEK_LockedAtEndOfFunction,
65   LEK_NotLockedAtEndOfFunction
66 };
67 
68 /// Handler class for thread safety warnings.
69 class ThreadSafetyHandler {
70 public:
71   typedef StringRef Name;
ThreadSafetyHandler()72   ThreadSafetyHandler() : IssueBetaWarnings(false) { }
73   virtual ~ThreadSafetyHandler();
74 
75   /// Warn about lock expressions which fail to resolve to lockable objects.
76   /// \param Kind -- the capability's name parameter (role, mutex, etc).
77   /// \param Loc -- the SourceLocation of the unresolved expression.
handleInvalidLockExp(StringRef Kind,SourceLocation Loc)78   virtual void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) {}
79 
80   /// Warn about unlock function calls that do not have a prior matching lock
81   /// expression.
82   /// \param Kind -- the capability's name parameter (role, mutex, etc).
83   /// \param LockName -- A StringRef name for the lock expression, to be printed
84   /// in the error message.
85   /// \param Loc -- The SourceLocation of the Unlock
handleUnmatchedUnlock(StringRef Kind,Name LockName,SourceLocation Loc)86   virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
87                                      SourceLocation Loc) {}
88 
89   /// Warn about an unlock function call that attempts to unlock a lock with
90   /// the incorrect lock kind. For instance, a shared lock being unlocked
91   /// exclusively, or vice versa.
92   /// \param LockName -- A StringRef name for the lock expression, to be printed
93   /// in the error message.
94   /// \param Kind -- the capability's name parameter (role, mutex, etc).
95   /// \param Expected -- the kind of lock expected.
96   /// \param Received -- the kind of lock received.
97   /// \param Loc -- The SourceLocation of the Unlock.
handleIncorrectUnlockKind(StringRef Kind,Name LockName,LockKind Expected,LockKind Received,SourceLocation Loc)98   virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
99                                          LockKind Expected, LockKind Received,
100                                          SourceLocation Loc) {}
101 
102   /// Warn about lock function calls for locks which are already held.
103   /// \param Kind -- the capability's name parameter (role, mutex, etc).
104   /// \param LockName -- A StringRef name for the lock expression, to be printed
105   /// in the error message.
106   /// \param Loc -- The location of the second lock expression.
handleDoubleLock(StringRef Kind,Name LockName,SourceLocation Loc)107   virtual void handleDoubleLock(StringRef Kind, Name LockName,
108                                 SourceLocation Loc) {}
109 
110   /// Warn about situations where a mutex is sometimes held and sometimes not.
111   /// The three situations are:
112   /// 1. a mutex is locked on an "if" branch but not the "else" branch,
113   /// 2, or a mutex is only held at the start of some loop iterations,
114   /// 3. or when a mutex is locked but not unlocked inside a function.
115   /// \param Kind -- the capability's name parameter (role, mutex, etc).
116   /// \param LockName -- A StringRef name for the lock expression, to be printed
117   /// in the error message.
118   /// \param LocLocked -- The location of the lock expression where the mutex is
119   ///               locked
120   /// \param LocEndOfScope -- The location of the end of the scope where the
121   ///               mutex is no longer held
122   /// \param LEK -- which of the three above cases we should warn for
handleMutexHeldEndOfScope(StringRef Kind,Name LockName,SourceLocation LocLocked,SourceLocation LocEndOfScope,LockErrorKind LEK)123   virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
124                                          SourceLocation LocLocked,
125                                          SourceLocation LocEndOfScope,
126                                          LockErrorKind LEK) {}
127 
128   /// Warn when a mutex is held exclusively and shared at the same point. For
129   /// example, if a mutex is locked exclusively during an if branch and shared
130   /// during the else branch.
131   /// \param Kind -- the capability's name parameter (role, mutex, etc).
132   /// \param LockName -- A StringRef name for the lock expression, to be printed
133   /// in the error message.
134   /// \param Loc1 -- The location of the first lock expression.
135   /// \param Loc2 -- The location of the second lock expression.
handleExclusiveAndShared(StringRef Kind,Name LockName,SourceLocation Loc1,SourceLocation Loc2)136   virtual void handleExclusiveAndShared(StringRef Kind, Name LockName,
137                                         SourceLocation Loc1,
138                                         SourceLocation Loc2) {}
139 
140   /// Warn when a protected operation occurs while no locks are held.
141   /// \param Kind -- the capability's name parameter (role, mutex, etc).
142   /// \param D -- The decl for the protected variable or function
143   /// \param POK -- The kind of protected operation (e.g. variable access)
144   /// \param AK -- The kind of access (i.e. read or write) that occurred
145   /// \param Loc -- The location of the protected operation.
handleNoMutexHeld(StringRef Kind,const NamedDecl * D,ProtectedOperationKind POK,AccessKind AK,SourceLocation Loc)146   virtual void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
147                                  ProtectedOperationKind POK, AccessKind AK,
148                                  SourceLocation Loc) {}
149 
150   /// Warn when a protected operation occurs while the specific mutex protecting
151   /// the operation is not locked.
152   /// \param Kind -- the capability's name parameter (role, mutex, etc).
153   /// \param D -- The decl for the protected variable or function
154   /// \param POK -- The kind of protected operation (e.g. variable access)
155   /// \param LockName -- A StringRef name for the lock expression, to be printed
156   /// in the error message.
157   /// \param LK -- The kind of access (i.e. read or write) that occurred
158   /// \param Loc -- The location of the protected operation.
159   virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
160                                   ProtectedOperationKind POK, Name LockName,
161                                   LockKind LK, SourceLocation Loc,
162                                   Name *PossibleMatch = nullptr) {}
163 
164   /// Warn when a function is called while an excluded mutex is locked. For
165   /// example, the mutex may be locked inside the function.
166   /// \param Kind -- the capability's name parameter (role, mutex, etc).
167   /// \param FunName -- The name of the function
168   /// \param LockName -- A StringRef name for the lock expression, to be printed
169   /// in the error message.
170   /// \param Loc -- The location of the function call.
handleFunExcludesLock(StringRef Kind,Name FunName,Name LockName,SourceLocation Loc)171   virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
172                                      Name LockName, SourceLocation Loc) {}
173 
issueBetaWarnings()174   bool issueBetaWarnings() { return IssueBetaWarnings; }
setIssueBetaWarnings(bool b)175   void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
176 
177 private:
178   bool IssueBetaWarnings;
179 };
180 
181 /// \brief Check a function's CFG for thread-safety violations.
182 ///
183 /// We traverse the blocks in the CFG, compute the set of mutexes that are held
184 /// at the end of each block, and issue warnings for thread safety violations.
185 /// Each block in the CFG is traversed exactly once.
186 void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
187                              ThreadSafetyHandler &Handler);
188 
189 /// \brief Helper function that returns a LockKind required for the given level
190 /// of access.
191 LockKind getLockKindFromAccessKind(AccessKind AK);
192 
193 }} // end namespace clang::thread_safety
194 #endif
195