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