Clang Project

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