Home | History | Annotate | Line # | Download | only in Analyses
      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 
     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.
     56 enum 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.
     69 enum 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.
     85 enum LockErrorKind {
     86   LEK_LockedSomeLoopIterations,
     87   LEK_LockedSomePredecessors,
     88   LEK_LockedAtEndOfFunction,
     89   LEK_NotLockedAtEndOfFunction
     90 };
     91 
     92 /// Handler class for thread safety warnings.
     93 class ThreadSafetyHandler {
     94 public:
     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 Kind, SourceLocation 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   /// \param LocPreviousUnlock -- If valid, the location of a previous Unlock.
    112   virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
    113                                      SourceLocation Loc,
    114                                      SourceLocation LocPreviousUnlock) {}
    115 
    116   /// Warn about an unlock function call that attempts to unlock a lock with
    117   /// the incorrect lock kind. For instance, a shared lock being unlocked
    118   /// exclusively, or vice versa.
    119   /// \param LockName -- A StringRef name for the lock expression, to be printed
    120   /// in the error message.
    121   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    122   /// \param Expected -- the kind of lock expected.
    123   /// \param Received -- the kind of lock received.
    124   /// \param LocLocked -- The SourceLocation of the Lock.
    125   /// \param LocUnlock -- The SourceLocation of the Unlock.
    126   virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
    127                                          LockKind Expected, LockKind Received,
    128                                          SourceLocation LocLocked,
    129                                          SourceLocation LocUnlock) {}
    130 
    131   /// Warn about lock function calls for locks which are already held.
    132   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    133   /// \param LockName -- A StringRef name for the lock expression, to be printed
    134   /// in the error message.
    135   /// \param LocLocked -- The location of the first lock expression.
    136   /// \param LocDoubleLock -- The location of the second lock expression.
    137   virtual void handleDoubleLock(StringRef Kind, Name LockName,
    138                                 SourceLocation LocLocked,
    139                                 SourceLocation LocDoubleLock) {}
    140 
    141   /// Warn about situations where a mutex is sometimes held and sometimes not.
    142   /// The three situations are:
    143   /// 1. a mutex is locked on an "if" branch but not the "else" branch,
    144   /// 2, or a mutex is only held at the start of some loop iterations,
    145   /// 3. or when a mutex is locked but not unlocked inside a function.
    146   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    147   /// \param LockName -- A StringRef name for the lock expression, to be printed
    148   /// in the error message.
    149   /// \param LocLocked -- The location of the lock expression where the mutex is
    150   ///               locked
    151   /// \param LocEndOfScope -- The location of the end of the scope where the
    152   ///               mutex is no longer held
    153   /// \param LEK -- which of the three above cases we should warn for
    154   virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
    155                                          SourceLocation LocLocked,
    156                                          SourceLocation LocEndOfScope,
    157                                          LockErrorKind LEK) {}
    158 
    159   /// Warn when a mutex is held exclusively and shared at the same point. For
    160   /// example, if a mutex is locked exclusively during an if branch and shared
    161   /// during the else branch.
    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 Loc1 -- The location of the first lock expression.
    166   /// \param Loc2 -- The location of the second lock expression.
    167   virtual void handleExclusiveAndShared(StringRef Kind, Name LockName,
    168                                         SourceLocation Loc1,
    169                                         SourceLocation Loc2) {}
    170 
    171   /// Warn when a protected operation occurs while no locks are held.
    172   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    173   /// \param D -- The decl for the protected variable or function
    174   /// \param POK -- The kind of protected operation (e.g. variable access)
    175   /// \param AK -- The kind of access (i.e. read or write) that occurred
    176   /// \param Loc -- The location of the protected operation.
    177   virtual void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
    178                                  ProtectedOperationKind POK, AccessKind AK,
    179                                  SourceLocation Loc) {}
    180 
    181   /// Warn when a protected operation occurs while the specific mutex protecting
    182   /// the operation is not locked.
    183   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    184   /// \param D -- The decl for the protected variable or function
    185   /// \param POK -- The kind of protected operation (e.g. variable access)
    186   /// \param LockName -- A StringRef name for the lock expression, to be printed
    187   /// in the error message.
    188   /// \param LK -- The kind of access (i.e. read or write) that occurred
    189   /// \param Loc -- The location of the protected operation.
    190   virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
    191                                   ProtectedOperationKind POK, Name LockName,
    192                                   LockKind LK, SourceLocation Loc,
    193                                   Name *PossibleMatch = nullptr) {}
    194 
    195   /// Warn when acquiring a lock that the negative capability is not held.
    196   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    197   /// \param LockName -- The name for the lock expression, to be printed in the
    198   /// diagnostic.
    199   /// \param Neg -- The name of the negative capability to be printed in the
    200   /// diagnostic.
    201   /// \param Loc -- The location of the protected operation.
    202   virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
    203                                      SourceLocation Loc) {}
    204 
    205   /// Warn when calling a function that a negative capability is not held.
    206   /// \param D -- The decl for the function requiring the negative capability.
    207   /// \param LockName -- The name for the lock expression, to be printed in the
    208   /// diagnostic.
    209   /// \param Loc -- The location of the protected operation.
    210   virtual void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
    211                                      SourceLocation Loc) {}
    212 
    213   /// Warn when a function is called while an excluded mutex is locked. For
    214   /// example, the mutex may be locked inside the function.
    215   /// \param Kind -- the capability's name parameter (role, mutex, etc).
    216   /// \param FunName -- The name of the function
    217   /// \param LockName -- A StringRef name for the lock expression, to be printed
    218   /// in the error message.
    219   /// \param Loc -- The location of the function call.
    220   virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
    221                                      Name LockName, SourceLocation Loc) {}
    222 
    223   /// Warn that L1 cannot be acquired before L2.
    224   virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
    225                                         Name L2Name, SourceLocation Loc) {}
    226 
    227   /// Warn that there is a cycle in acquired_before/after dependencies.
    228   virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
    229 
    230   /// Called by the analysis when starting analysis of a function.
    231   /// Used to issue suggestions for changes to annotations.
    232   virtual void enterFunction(const FunctionDecl *FD) {}
    233 
    234   /// Called by the analysis when finishing analysis of a function.
    235   virtual void leaveFunction(const FunctionDecl *FD) {}
    236 
    237   bool issueBetaWarnings() { return IssueBetaWarnings; }
    238   void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
    239 
    240 private:
    241   bool IssueBetaWarnings = false;
    242 };
    243 
    244 /// Check a function's CFG for thread-safety violations.
    245 ///
    246 /// We traverse the blocks in the CFG, compute the set of mutexes that are held
    247 /// at the end of each block, and issue warnings for thread safety violations.
    248 /// Each block in the CFG is traversed exactly once.
    249 void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
    250                              ThreadSafetyHandler &Handler,
    251                              BeforeSet **Bset);
    252 
    253 void threadSafetyCleanup(BeforeSet *Cache);
    254 
    255 /// Helper function that returns a LockKind required for the given level
    256 /// of access.
    257 LockKind getLockKindFromAccessKind(AccessKind AK);
    258 
    259 } // namespace threadSafety
    260 } // namespace clang
    261 
    262 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
    263