Home | History | Annotate | Download | only in Analyses
      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;
     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.
     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
     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.
     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.
    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
    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.
    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.
    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.
    171   virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
    172                                      Name LockName, SourceLocation Loc) {}
    173 
    174   bool issueBetaWarnings() { return IssueBetaWarnings; }
    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