malhar1995 updated this revision to Diff 99179.
malhar1995 added a comment.

Added context. 
Also, I removed the inclusion of iostream and also added the repetitive code to 
the function setAppropriateLockState.
Currently working on finding various corner cases and invariants.


Repository:
  rL LLVM

https://reviews.llvm.org/D32449

Files:
  .DS_Store
  lib/.DS_Store
  lib/StaticAnalyzer/.DS_Store
  lib/StaticAnalyzer/Checkers/.DS_Store
  lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp

Index: lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -25,30 +25,34 @@
 namespace {
 
 struct LockState {
-  enum Kind { Destroyed, Locked, Unlocked } K;
+  enum Kind { Destroyed, Locked, Unlocked, SchrodingerLocked, SchrodingerUnlocked } K;
 
 private:
   LockState(Kind K) : K(K) {}
 
 public:
   static LockState getLocked() { return LockState(Locked); }
   static LockState getUnlocked() { return LockState(Unlocked); }
   static LockState getDestroyed() { return LockState(Destroyed); }
+  static LockState getSchrodingerLocked() { return LockState(SchrodingerLocked); }
+  static LockState getSchrodingerUnlocked() { return LockState(SchrodingerUnlocked); }
 
   bool operator==(const LockState &X) const {
     return K == X.K;
   }
 
   bool isLocked() const { return K == Locked; }
   bool isUnlocked() const { return K == Unlocked; }
   bool isDestroyed() const { return K == Destroyed; }
+  bool isSchrodingerLocked() const { return K == SchrodingerLocked; }
+  bool isSchrodingerUnlocked() const { return K == SchrodingerUnlocked; }
 
   void Profile(llvm::FoldingSetNodeID &ID) const {
     ID.AddInteger(K);
   }
 };
 
-class PthreadLockChecker : public Checker< check::PostStmt<CallExpr> > {
+class PthreadLockChecker : public Checker< check::PostStmt<CallExpr>, check::DeadSymbols > {
   mutable std::unique_ptr<BugType> BT_doublelock;
   mutable std::unique_ptr<BugType> BT_doubleunlock;
   mutable std::unique_ptr<BugType> BT_destroylock;
@@ -61,21 +65,24 @@
   };
 public:
   void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
 
   void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock,
                    bool isTryLock, enum LockingSemantics semantics) const;
 
   void ReleaseLock(CheckerContext &C, const CallExpr *CE, SVal lock) const;
   void DestroyLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const;
   void InitLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const;
   void reportUseDestroyedBug(CheckerContext &C, const CallExpr *CE) const;
+  ProgramStateRef setAppropriateLockState(ProgramStateRef state, const MemRegion* lockR) const;
 };
 } // end anonymous namespace
 
 // GDM Entry for tracking lock state.
 REGISTER_LIST_WITH_PROGRAMSTATE(LockSet, const MemRegion *)
 
 REGISTER_MAP_WITH_PROGRAMSTATE(LockMap, const MemRegion *, LockState)
+REGISTER_MAP_WITH_PROGRAMSTATE(DestroyRetVal, const MemRegion *, SymbolRef)
 
 void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
                                        CheckerContext &C) const {
@@ -120,16 +127,40 @@
     InitLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
 }
 
+ProgramStateRef PthreadLockChecker::setAppropriateLockState(ProgramStateRef state, const MemRegion* lockR) const {
+  const SymbolRef* sym = state->get<DestroyRetVal>(lockR);
+  if(sym){
+    const LockState* lstate = state->get<LockMap>(lockR);
+    if(lstate){
+      ConstraintManager &CMgr = state->getConstraintManager();
+      ConditionTruthVal retZero = CMgr.isNull(state, *sym);
+      if(retZero.isConstrainedFalse()){
+        if(lstate->isSchrodingerLocked())
+          state = state->set<LockMap>(lockR, LockState::getLocked());
+        else if(lstate->isSchrodingerUnlocked())
+          state = state->set<LockMap>(lockR, LockState::getUnlocked());
+      }
+      else{
+        if(!lstate || lstate->isSchrodingerLocked() || lstate->isSchrodingerUnlocked())
+          state = state->set<LockMap>(lockR, LockState::getDestroyed());
+      }
+    }
+  }
+  return state;
+}
+
 void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
                                      SVal lock, bool isTryLock,
                                      enum LockingSemantics semantics) const {
 
   const MemRegion *lockR = lock.getAsRegion();
   if (!lockR)
-    return;
+    return; 
 
   ProgramStateRef state = C.getState();
 
+  state = setAppropriateLockState(state, lockR);
+
   SVal X = state->getSVal(CE, C.getLocationContext());
   if (X.isUnknownOrUndef())
     return;
@@ -198,6 +229,8 @@
 
   ProgramStateRef state = C.getState();
 
+  state = setAppropriateLockState(state, lockR);
+
   if (const LockState *LState = state->get<LockMap>(lockR)) {
     if (LState->isUnlocked()) {
       if (!BT_doubleunlock)
@@ -253,9 +286,32 @@
 
   ProgramStateRef State = C.getState();
 
+  State = setAppropriateLockState(State, LockR);
+
+  // CHECK THIS
   const LockState *LState = State->get<LockMap>(LockR);
-  if (!LState || LState->isUnlocked()) {
-    State = State->set<LockMap>(LockR, LockState::getDestroyed());
+  if(!LState){
+    SVal X = State->getSVal(CE, C.getLocationContext());
+    if (X.isUnknownOrUndef()){
+      return;
+    }
+
+    DefinedSVal retVal = X.castAs<DefinedSVal>();
+    retVal.dump();
+    SymbolRef sym = retVal.getAsSymbol();
+    State = State->set<DestroyRetVal>(LockR, sym);
+    C.addTransition(State);
+    return;
+  }
+  if (LState->isUnlocked()) {
+    SVal X = State->getSVal(CE, C.getLocationContext());
+    if (X.isUnknownOrUndef())
+      return;
+
+    DefinedSVal retVal = X.castAs<DefinedSVal>();
+    SymbolRef sym = retVal.getAsSymbol();
+    State = State->set<DestroyRetVal>(LockR, sym);
+    State = State->set<LockMap>(LockR, LockState::getSchrodingerUnlocked());
     C.addTransition(State);
     return;
   }
@@ -327,6 +383,37 @@
   Report->addRange(CE->getArg(0)->getSourceRange());
   C.emitReport(std::move(Report));
 }
+void PthreadLockChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                           CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  ConstraintManager &CMgr = State->getConstraintManager();
+
+  DestroyRetValTy TrackedSymbols = State->get<DestroyRetVal>();
+  for (DestroyRetValTy::iterator I = TrackedSymbols.begin(),
+                             E = TrackedSymbols.end(); I != E; ++I) {
+    SymbolRef Sym = I->second;
+    const MemRegion* lockR = I->first;
+    bool IsSymDead = SymReaper.isDead(Sym);
+    const LockState* LState = State->get<LockMap>(lockR); 
+    // Remove the dead symbol from the return value symbols map.
+    if (IsSymDead){
+      ConditionTruthVal retZero = CMgr.isNull(State, Sym);
+      if(retZero.isConstrainedFalse()){
+        if(LState && LState->isSchrodingerLocked())
+          State = State->set<LockMap>(lockR, LockState::getLocked());
+        else if(LState && LState->isSchrodingerUnlocked())
+          State = State->set<LockMap>(lockR, LockState::getUnlocked());
+      }
+      else{
+        // IS THIS CORRECT?
+        if(!LState || LState->isSchrodingerUnlocked() || LState->isSchrodingerLocked())
+          State = State->set<LockMap>(lockR, LockState::getDestroyed());
+      }
+      State = State->remove<DestroyRetVal>(lockR);
+    }
+  }
+  C.addTransition(State);
+}
 
 void ento::registerPthreadLockChecker(CheckerManager &mgr) {
   mgr.registerChecker<PthreadLockChecker>();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to